appifier 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/VERSION +1 -1
  4. data/appifier.gemspec +6 -0
  5. data/exe/app +10 -0
  6. data/lib/appifier/actors/collector.rb +20 -16
  7. data/lib/appifier/actors/generator.rb +14 -3
  8. data/lib/appifier/actors/retriever.rb +21 -5
  9. data/lib/appifier/cli/configuration.rb +40 -2
  10. data/lib/appifier/cli/datasets.rb +75 -0
  11. data/lib/appifier/cli/templates.rb +53 -5
  12. data/lib/appifier/cli.rb +36 -11
  13. data/lib/appifier/components/Appifile.rb +52 -10
  14. data/lib/appifier/components/dataset.rb +60 -0
  15. data/lib/appifier/components/template.rb +125 -0
  16. data/lib/appifier/setup.rb +26 -3
  17. data/lib/appifier.rb +6 -10
  18. data/samples/baddummy/Appifile +18 -0
  19. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/.rspec +0 -0
  20. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/Rakefile +0 -0
  21. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/config.ru +0 -0
  22. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/exe/%%APPNAME.downcase%% +0 -0
  23. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/lib/%%APPNAME.downcase%%.rb +0 -0
  24. data/samples/baddummy/skeleton/%%APPNAME.downcase%%/spec/%%APPNAME.downcase%%_spec.rb +0 -0
  25. data/samples/baddummy.tgz +0 -0
  26. data/samples/dummy/Appifile +8 -1
  27. data/samples/dummy/README.md +4 -0
  28. data/samples/dummy.tgz +0 -0
  29. data/samples/dummy_warn/Appifile +19 -0
  30. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/.rspec +0 -0
  31. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/Rakefile +0 -0
  32. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/config.ru +0 -0
  33. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/exe/%%APPNAME.downcase%% +0 -0
  34. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/lib/%%APPNAME.downcase%%.rb +0 -0
  35. data/samples/dummy_warn/skeleton/%%APPNAME.downcase%%/spec/%%APPNAME.downcase%%_spec.rb +0 -0
  36. metadata +111 -7
  37. data/lib/appifier/components/templates.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aeea227ea8e3eaa87c58fcbd7333297f73b7e2c82f7ba51da9b8bccb4f979f05
4
- data.tar.gz: 3121f0753db7fbc4b8d68f2acfaf141cf9ee9785f5abfc5edca2b5a645faa942
3
+ metadata.gz: bc6decc46de1031b29f5752b5a8e9e19ff34503910f853a796c13becde17f516
4
+ data.tar.gz: 7cf6cff0288638c120c74f815087ea5e668a1299b1cde1407f0e42b46286057a
5
5
  SHA512:
6
- metadata.gz: d7aceeba188e836380bd52eebdfb87839c6227f79282e2ae90fe12d1486d03c4dbb53147c61abb84d4aab172bca8e10b8d7aa419b214e0f0bb151bbd30e4a17c
7
- data.tar.gz: 90fa233237110cfc8c815e6d3002dbc831eaf08b9979d9f0d499f9d08228768c87e519f212fde8241ee9c944f158d90cadbe9924fc4031bd8a8eaa42a6165873
6
+ metadata.gz: 1383dc7d00f324f6831066639eb4ae19577571ba6c3cf0eaa712fae13d41997ffa56ae10b90d74a9249c8fe8a18f29f1bc24b103f9a2bdaccb28934dc594ccd0
7
+ data.tar.gz: adb3a368020d53a60a880baba3f688b65e8b608224c1227e26acd9850d76753c85ddd64e77abe59635eed4f075369884eecadf29275ce8717866de29da36bb5d
data/Gemfile CHANGED
@@ -3,3 +3,4 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.3.0
data/appifier.gemspec CHANGED
@@ -37,4 +37,10 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency 'carioca', '~> 2.0.9'
38
38
  spec.add_dependency 'thor', '~> 1.2'
39
39
  spec.add_dependency 'tty-prompt', '~> 0.23.1'
40
+ spec.add_dependency "thot", "~> 1.0"
41
+ spec.add_dependency "git", "~> 1.12"
42
+ spec.add_dependency "schash","~> 0.1.2"
43
+ spec.add_dependency "tty-tree", "~> 0.4.0"
44
+ spec.add_dependency "tty-markdown", "~> 0.7.0"
45
+ spec.add_dependency "tty-link", "~> 0.1.1"
40
46
  end
data/exe/app ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'appifier'
5
+
6
+ require 'appifier/cli'
7
+
8
+ include Appifier::CLI
9
+
10
+ MainCommand.start(ARGV)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require "tty-prompt"
2
+
3
3
 
4
4
  module Appifier
5
5
  module Actors
@@ -7,6 +7,7 @@ module Appifier
7
7
 
8
8
  extend Carioca::Injector
9
9
  inject service: :output
10
+ inject service: :finisher
10
11
 
11
12
  attr_accessor :dataset
12
13
  attr_reader :template
@@ -19,22 +20,25 @@ module Appifier
19
20
 
20
21
 
21
22
  def collect
22
-
23
- appifilename = "#{File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)}/#{template}/Appifile"
24
- appifile = Appifier::Components::Appifile::new path: appifilename
25
- prompt = TTY::Prompt.new
26
- @dataset = {}
27
- appifile.dataset_rules.each do |name, rule|
28
- default = (rule[:default])? rule[:default] : ""
29
- @dataset[name] = prompt.ask("Give #{rule[:description]} : ", default: default) do |q|
30
- q.required true
31
- q.validate Regexp.new(rule[:format]) if rule[:format]
32
- end
23
+ begin
24
+ appifilename = "#{File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)}/#{template}/Appifile"
25
+ appifile = Appifier::Components::Appifile::new path: appifilename
26
+ prompt = TTY::Prompt.new
27
+ @dataset = {}
28
+ appifile.dataset_rules.each do |name, rule|
29
+ default = (rule[:default])? rule[:default] : ""
30
+ @dataset[name] = prompt.ask("Give #{rule[:description]} : ", default: default) do |q|
31
+ q.required true
32
+ q.validate Regexp.new(rule[:format]) if rule[:format]
33
+ end
34
+ end
35
+ write_dataset template: @template, data: @dataset
36
+ @collected = true
37
+ output.info "Dataset recorded for #{@template}"
38
+ rescue TTY::Reader::InputInterrupt
39
+ output.warn "Interactive collect interrupted"
40
+ finisher.terminate exit_case: :interrupt
33
41
  end
34
- write_dataset template: @template, data: @dataset
35
- @collected = true
36
- output.info "Dataset recorded for #{@template}"
37
-
38
42
  end
39
43
 
40
44
  def collected?
@@ -9,8 +9,9 @@ module Appifier
9
9
  inject service: :output
10
10
 
11
11
 
12
- def initialize(src_root:, target_root:, dataset: )
13
- @src_root = src_root
12
+ def initialize(template_root:, target_root:, dataset: )
13
+ @template_root = template_root
14
+ @src_root = "#{template_root}/skeleton"
14
15
  @target_root = target_root
15
16
  @target_folders = []
16
17
  @target_files = []
@@ -19,7 +20,7 @@ module Appifier
19
20
  @src_paths.delete_if { |file| file =~ %r{/\.$} }
20
21
  @src_folders = @src_paths.select { |item| File.directory? item }
21
22
  @src_files = @src_paths.select { |item| File.file? item }
22
- raise 'Application template not found' unless File.exist?(src_root)
23
+ raise 'Application template not found' unless File.exist?(@template_root)
23
24
  end
24
25
 
25
26
  def generate(dry_run: false, force: false)
@@ -31,6 +32,7 @@ module Appifier
31
32
  generate_folders dry_run: dry_run
32
33
  output.info 'Generate files'
33
34
  generate_files dry_run: dry_run
35
+ copy_appifile dry_run: dry_run
34
36
  end
35
37
 
36
38
  def calculate
@@ -53,6 +55,15 @@ module Appifier
53
55
  end
54
56
  end
55
57
 
58
+
59
+ def copy_appifile(dry_run:)
60
+ output.info "Copy Appifile in #{@target_root} :"
61
+ action = dry_run ? :skipped : :ok
62
+ FileUtils.cp "#{@template_root}/Appifile", @target_root unless dry_run
63
+ output.send action, "Install Appifile"
64
+ end
65
+
66
+
56
67
  def generate_files(dry_run:)
57
68
  output.info "Target files to create in #{@target_root} :"
58
69
  @src_files.each_with_index do |path, index|
@@ -1,18 +1,27 @@
1
1
  # frozen_string_literal: false
2
-
2
+ require 'git'
3
+ require 'uri'
3
4
  module Appifier
4
5
  module Actors
5
6
  module Retrivers
6
7
  class Git
7
- def self.get(origin:, destination:);
8
- raise 'not yest implemented'
8
+ def self.get(origin:, destination:)
9
+ uri = URI.parse(origin)
10
+ path = uri.path
11
+ name = File.basename(path, ".git")
12
+ raise "Git URL format failed (only http bare git format)" if name.include?('.')
13
+ ::Git.clone(origin, nil, path: destination)
14
+ return name
9
15
  end
10
16
  end
11
17
 
12
18
  class Archive
13
19
  def self.get(origin:, destination:)
14
20
  raise "Archive : #{origin} not found" unless File::exist? origin
21
+ name = File.basename(origin, ".tgz")
22
+ raise "Template name format failed : must be .tgz file" if name.include?('.')
15
23
  untar_gz archive: origin, destination: destination
24
+ return name
16
25
  end
17
26
  end
18
27
  end
@@ -27,11 +36,18 @@ module Appifier
27
36
  @origin = origin
28
37
  @type = type
29
38
  @destination = destination
30
- output.info "retrieving template from #{origin}"
39
+ output.info "Retrieving template from #{origin}"
31
40
  end
32
41
 
33
42
  def get
34
- TYPE[@type].get origin: @origin, destination: @destination
43
+ template = TYPE[@type].get origin: @origin, destination: @destination
44
+ result = Appifier::Components::Template.validate!(template: template)
45
+ unless result[:error].empty?
46
+ output.ko "Template #{template} retrieving cancelled"
47
+ Appifier::Components::Template.rm(template) unless result[:error].empty?
48
+
49
+ end
50
+ return result
35
51
  end
36
52
  end
37
53
  end
@@ -4,13 +4,51 @@ module Appifier
4
4
  module CLI
5
5
  module Subcommands
6
6
  class Configuration < ::Thor
7
+
8
+ def initialize(*args)
9
+ super
10
+ @output = Carioca::Registry.get.get_service name: :output
11
+ @finisher = Carioca::Registry.get.get_service name: :finisher
12
+ end
13
+
7
14
  # Thor method : running of Appifier sanitycheck
8
15
  desc 'sanitycheck', 'Verify installation of Appifier for user'
9
- def sanitycheck; end
16
+ def sanitycheck
17
+ Appifier::Configuration::Checker.sanitycheck
18
+
19
+ end
20
+
21
+
22
+ # Thor method : running of Appifier setup for config rebuild [DANGER]
23
+ desc 'reset', 'Running Appifier setup for configuration rebuild [DANGER]'
24
+ long_desc <<-LONGDESC
25
+ Running Appifier setup for configuration rebuild [DANGER]\n
26
+ with --force => force collect, and destroy previous configuration [DANGER]
27
+ LONGDESC
28
+ option :force, type: :boolean, aliases: '-F'
29
+ def reset
30
+ begin
31
+ raise "[DANGER] please add -F if you sure : appifier configuration reset -F" unless options[:force]
32
+ @output.warn "Appifier reset configuration"
33
+ Appifier::Configuration.setup force: true
34
+ @finisher.terminate exit_case: :quiet_exit
35
+ rescue RuntimeError => e
36
+ @output.error e.message
37
+ @finisher.terminate exit_case: :error_exit
38
+ end
39
+
40
+ end
10
41
 
11
42
  # Thor method : Getting the current Appifier version
12
43
  desc 'version', 'Display current Appifier version'
13
- def version; end
44
+ def version;
45
+ @output.info "Querying version"
46
+ puts 'Appifier (c) Ultragreen Software'
47
+ puts "Camille PAQUET - Romain GEORGES "
48
+ puts TTY::Link.link_to("http://www.ultragreen.net", "http://www.ultragreen.net")
49
+ puts "Version #{Appifier::VERSION}"
50
+ @finisher.terminate exit_case: :quiet_exit
51
+ end
14
52
  end
15
53
  end
16
54
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+ module Appifier
3
+ module CLI
4
+ module Subcommands
5
+ class Datasets < ::Thor
6
+
7
+ def initialize(*args)
8
+ super
9
+ @output = Carioca::Registry.get.get_service name: :output
10
+ @finisher = Carioca::Registry.get.get_service name: :finisher
11
+ end
12
+
13
+ # Thor method : list availables datasets in user bundle
14
+ desc 'ls', 'list defined datasets in user bundle'
15
+ def ls
16
+ begin
17
+ Appifier::Components::Dataset::list
18
+ @finisher.terminate exit_case: :quiet_exit
19
+ rescue RuntimeError => e
20
+ @output.error e.message
21
+ @finisher.terminate exit_case: :error_exit
22
+ end
23
+ end
24
+
25
+ # Thor method : show a specific dataset in user bundle
26
+ desc 'show DATASET', 'show a specific dataset in user bundle'
27
+ def show(dataset)
28
+ begin
29
+ Appifier::Components::Dataset::show dataset
30
+ @finisher.terminate exit_case: :quiet_exit
31
+ rescue RuntimeError => e
32
+ @output.error e.message
33
+ @finisher.terminate exit_case: :error_exit
34
+ end
35
+ end
36
+
37
+ # Thor method : remove a dataset from user bundle
38
+ desc 'rm DATASET', 'Remove dataset from user bundle'
39
+ def rm(dataset)
40
+ begin
41
+ Appifier::Components::Dataset::rm(dataset)
42
+ @finisher.terminate exit_case: :quiet_exit
43
+ rescue RuntimeError => e
44
+ @output.error e.message
45
+ @finisher.terminate exit_case: :error_exit
46
+ end
47
+ end
48
+
49
+
50
+ # Thor method : Prune orphans datasets in user bundle
51
+ desc 'prune', 'Prune orphans datasets in user bundle'
52
+ long_desc <<-LONGDESC
53
+ Prune orphans datasets in user bundle\n
54
+ with --force, force pruning of dataset [DANGER]
55
+ LONGDESC
56
+ option :force, type: :boolean, aliases: '-F'
57
+ def prune
58
+ begin
59
+ ok = (options[:force]) ? true : TTY::Prompt.new.yes?("Do you want to prune datasets?")
60
+ if ok
61
+ Appifier::Components::Dataset::prune
62
+ @finisher.terminate exit_case: :quiet_exit
63
+ else
64
+ puts "Pruning cancelled"
65
+ @finisher.terminate exit_case: :quiet_exit
66
+ end
67
+ rescue TTY::Reader::InputInterrupt
68
+ @output.warn "Command interrupted"
69
+ @finisher.terminate exit_case: :interrupt
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
-
2
+ require 'tty-markdown'
3
3
  module Appifier
4
4
  module CLI
5
5
  module Subcommands
@@ -14,15 +14,63 @@ module Appifier
14
14
  # Thor method : list availables templates in user bundle
15
15
  desc 'ls', 'list templates availables in user bundle'
16
16
  def ls
17
- Appifier::Components::Templates::list
18
- @finisher.terminate exit_case: :error_exit
17
+ begin
18
+ Appifier::Components::Template::list
19
+ @finisher.terminate exit_case: :quiet_exit
20
+ rescue RuntimeError => e
21
+ @output.error e.message
22
+ @finisher.terminate exit_case: :error_exit
23
+ end
19
24
  end
20
25
 
21
26
  # Thor method : remove a template from user bundle
22
- desc 'rm', 'rm templates from user bundle'
27
+ desc 'rm TEMPLATE', 'Remove templates from user bundle'
23
28
  def rm(template)
24
29
  begin
25
- Appifier::Components::Templates::rm(template)
30
+ Appifier::Components::Template::rm(template)
31
+ @finisher.terminate exit_case: :quiet_exit
32
+ rescue RuntimeError => e
33
+ @output.error e.message
34
+ @finisher.terminate exit_case: :error_exit
35
+ end
36
+ end
37
+
38
+ # Thor method : show information for a specific template in user bundle
39
+ desc 'show TEMPLATE', 'show information for a specific template in user bundle'
40
+ def show(template)
41
+ begin
42
+ Appifier::Components::Template::show(template)
43
+ temp = Appifier::Components::Template::new(template: template)
44
+ if temp.readme?
45
+ puts " "
46
+ puts TTY::Markdown.parse_file(temp.readme_path)
47
+ end
48
+
49
+ @finisher.terminate exit_case: :quiet_exit
50
+ rescue RuntimeError => e
51
+ @output.error e.message
52
+ @finisher.terminate exit_case: :error_exit
53
+ end
54
+ end
55
+
56
+ # Thor method : display directory tree view for a specific template in user bundle
57
+ desc 'treeview TEMPLATE', 'display directory tree view for a specific template in user bundle'
58
+ def treeview(template)
59
+ begin
60
+ Appifier::Components::Template::treeview(template)
61
+ @finisher.terminate exit_case: :quiet_exit
62
+ rescue RuntimeError => e
63
+ @output.error e.message
64
+ @finisher.terminate exit_case: :error_exit
65
+ end
66
+ end
67
+
68
+ # Thor method : lint a specific template in user bundle
69
+ desc 'lint TEMPLATE', 'Lint a specific template in user bundle'
70
+ def lint(template)
71
+ begin
72
+ Appifier::Components::Template::lint(template)
73
+ @finisher.terminate exit_case: :quiet_exit
26
74
  rescue RuntimeError => e
27
75
  @output.error e.message
28
76
  @finisher.terminate exit_case: :error_exit
data/lib/appifier/cli.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  require 'appifier'
4
- require 'thor'
5
4
 
6
5
  Dir["#{File.dirname(__FILE__)}/cli/*.rb"].sort.each { |file| require file }
7
6
 
@@ -22,6 +21,9 @@ module Appifier
22
21
  true
23
22
  end
24
23
 
24
+ desc 'datasets SUBCOMMAND ...ARGS', 'Managing apps datasets'
25
+ subcommand 'datasets', Subcommands::Datasets
26
+
25
27
  desc 'templates SUBCOMMAND ...ARGS', 'Managing apps templates'
26
28
  subcommand 'templates', Subcommands::Templates
27
29
 
@@ -29,28 +31,45 @@ module Appifier
29
31
  subcommand 'configuration', Subcommands::Configuration
30
32
 
31
33
  # Thor method : running of Appifier generate
32
- desc 'generate TEMPLATE [TARGET]', 'Generate application from bundled template'
34
+ desc 'generate TEMPLATE [TARGET]', 'Generate application from bundled template (IF TARGET ommited use the current path as ROOTPATH)'
33
35
  long_desc <<-LONGDESC
34
36
  Generate application from bundled template\n
35
- with --simulate, only simulate folders and files installed
37
+ (IF TARGET ommited use the current path as ROOTPATH)\n
38
+ with --simulate, only simulate folders and files installed\n
36
39
  with --force, force regeneration of application, remove old files [DANGER]
37
40
  LONGDESC
38
41
  option :simulate, type: :boolean, aliases: '-s'
39
42
  option :force, type: :boolean, aliases: '-F'
40
43
  def generate(template, target = '.')
41
44
  root = "#{File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)}/#{template}"
42
- source = "#{root}/skeleton"
43
-
45
+ unless File::exist? root
46
+ @output.error "Template not found #{template}"
47
+ @finisher.terminate exit_case: :error_exit
48
+ end
44
49
  if File::exist? File::expand_path("#{DEFAULT_DATASETS_PATH}/#{template}.yml") then
45
50
  dataset = open_dataset(template: template)
46
51
  @output.info "Dataset file found for #{template}"
47
52
  else
48
- @output.ko "Dataset file not found for #{template}"
49
- @finisher.terminate exit_case: :error_exit
53
+ begin
54
+ @output.warn "Dataset file not found for #{template}"
55
+ if TTY::Prompt.new.yes?("Do you want to collect dataset interactively ?")
56
+ @output.info "Beginning interactive Dataset input for #{template}"
57
+ collector = Appifier::Actors::Collector.new template: template
58
+ collector.collect
59
+ dataset = open_dataset(template: template)
60
+ else
61
+ puts "=> Exiting run 'appifier collect #{template}' for collecting data"
62
+ puts " (use -S for collecting from STDIN or -f <FILE>) "
63
+ @finisher.terminate exit_case: :quiet_exit
64
+ end
65
+ rescue TTY::Reader::InputInterrupt
66
+ @output.warn "Command interrupted"
67
+ @finisher.terminate exit_case: :interrupt
68
+ end
50
69
  end
51
70
 
52
71
  begin
53
- generator = Appifier::Actors::Generator.new src_root: source, target_root: File.expand_path(target), dataset: dataset
72
+ generator = Appifier::Actors::Generator.new template_root: root, target_root: File.expand_path(target), dataset: dataset
54
73
  generator.generate dry_run: options[:simulate], force: options[:force]
55
74
  @finisher.terminate exit_case: :quiet_exit
56
75
  rescue RuntimeError => e
@@ -70,7 +89,13 @@ module Appifier
70
89
  begin
71
90
  type = options[:type].to_sym
72
91
  retriever = Appifier::Actors::Retriever.new type: type, origin: origin
73
- retriever.get
92
+ results = retriever.get
93
+ @output.info "Detail of notifications : " unless results[:error].empty? and results[:warn].empty? and results[:cleaned].empty?
94
+ [:error, :warn].each do |level|
95
+ results[level].each { |value| @output.send level, "#{level.to_s} : #{value}" }
96
+ end
97
+ results[:cleaned].each { |value| @output.ok "cleaned : #{value}" }
98
+ @finisher.terminate exit_case: :error_exit unless results[:error].empty?
74
99
  @finisher.terminate exit_case: :quiet_exit
75
100
  rescue RuntimeError => e
76
101
  @output.error e.message
@@ -82,8 +107,8 @@ module Appifier
82
107
  desc 'collect TEMPLATE', 'Collect dataset for an application template in user templates bundle'
83
108
  long_desc <<-LONGDESC
84
109
  Collect dataset for an application template in user templates bundle\n
85
- with --force => force collect, and destroy previous Dataset [DANGER]
86
- with --file FILENAME get data from à YAML File
110
+ with --force => force collect, and destroy previous Dataset [DANGER]\n
111
+ with --file FILENAME get data from à YAML File\n
87
112
  with --stdin get data from STDIN
88
113
 
89
114
  LONGDESC
@@ -1,3 +1,5 @@
1
+ require 'schash'
2
+
1
3
  module Appifier
2
4
  module Components
3
5
  class Appifile
@@ -6,8 +8,11 @@ module Appifier
6
8
 
7
9
  def initialize(path:)
8
10
  @path = path
9
- @content = {}
10
- openfile
11
+ begin
12
+ @content = open_yaml filename: @path
13
+ rescue RuntimeError
14
+ raise "Appifile missing"
15
+ end
11
16
  end
12
17
 
13
18
  def dataset_rules
@@ -18,17 +23,54 @@ module Appifier
18
23
  @content[:actions]
19
24
  end
20
25
 
21
- private
22
- def openfile
23
- raise 'Appifile not foud' unless File::exist? @path
26
+ def self.validate!(path:)
27
+ appifile = {}
28
+ res = {status: :ok, warn: [], error: [], cleaned: []}
24
29
  begin
25
- @content = YAML.load_file(@path)
26
- rescue StandardError => e
27
- raise e.message
30
+ appifile = open_yaml filename: path
31
+ validator = Schash::Validator.new do
32
+ {
33
+ template: {
34
+ authors: optional(array_of(string)),
35
+ version: numeric,
36
+ contact: optional(string),
37
+ description: optional(string),
38
+ dataset: {
39
+
40
+ }
41
+ },
42
+ actions: {
43
+ deploy: {},
44
+ run: {},
45
+ build: {},
46
+ publish: {},
47
+ test: {},
48
+ },
49
+ }
50
+
51
+ end
52
+
53
+ dataset_rules_validator = Schash::Validator.new do
54
+ {
55
+ format: string,
56
+ description: string,
57
+ default: optional(string)
58
+ }
59
+ end
60
+
61
+
62
+ result = validator.validate(appifile)
63
+ result.each {|item| res[:error].push "Appifiler : //#{item.position.join('/')} #{item.message}"}
64
+ appifile[:template][:dataset].each do |rule, definition|
65
+ result = dataset_rules_validator.validate definition
66
+ result.each {|item| res[:error].push "Appifiler : //template/dataset/#{rule}/#{item.position.join('/')} #{item.message}"}
67
+ end
68
+ rescue RuntimeError
69
+ res[:error].push "Appifile missing"
28
70
  end
29
-
30
-
71
+ return res
31
72
  end
73
+
32
74
  end
33
75
  end
34
76
  end
@@ -0,0 +1,60 @@
1
+ module Appifier
2
+ module Components
3
+ class Dataset
4
+
5
+ extend Carioca::Injector
6
+ inject service: :output
7
+
8
+
9
+ def self.list
10
+ output.info "List of available Datasets for user : #{current_user} :"
11
+ templates_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
12
+ datasets_path = File.expand_path(Appifier::DEFAULT_DATASETS_PATH)
13
+ templates = Dir.glob("#{templates_path}/*").map { |item| item.delete_prefix("#{templates_path}/") }
14
+ Dir.glob("#{datasets_path}/*").map { |item| item.delete_prefix("#{datasets_path}/") }.each do |file|
15
+ dataset = File::basename(file,'.yml')
16
+ res = dataset; res << " [TEMPLATE MISSING]" unless templates.include? dataset
17
+ output.item res
18
+ end
19
+ end
20
+
21
+
22
+ def self.prune
23
+ output.info "Pruning Datasets for user : #{current_user} :"
24
+ templates_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
25
+ datasets_path = File.expand_path(Appifier::DEFAULT_DATASETS_PATH)
26
+ templates = Dir.glob("#{templates_path}/*").map { |item| item.delete_prefix("#{templates_path}/") }
27
+ Dir.glob("#{datasets_path}/*").each do |file|
28
+ dataset = File::basename(file,'.yml')
29
+ unless templates.include? dataset
30
+ FileUtils::rm file
31
+ output.item "Pruned : #{dataset}"
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ def self.show(dataset)
38
+ raise "Not yet Implemented"
39
+ end
40
+
41
+ def self.rm(dataset)
42
+ output.info "Removing dataset #{dataset} for user : #{current_user}"
43
+ dataset_path = File.expand_path(Appifier::DEFAULT_DATASETS_PATH)
44
+ begin
45
+ if File::exist? "#{dataset_path}/#{dataset}.yml"
46
+ FileUtils.rm_rf "#{dataset_path}/#{dataset}.yml"
47
+ output.ok "Dataset #{dataset} deleted of bundle for user #{current_user}"
48
+ else
49
+ raise "Dataset #{dataset} not found in bundle for user #{current_user}"
50
+ end
51
+ rescue Errno::ENOENT
52
+ raise "Dataset #{dataset} not found in bundle for user #{current_user}"
53
+ end
54
+ end
55
+
56
+
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+ require 'tty-tree'
3
+ module Appifier
4
+ module Components
5
+
6
+
7
+ class Template
8
+ extend Carioca::Injector
9
+ inject service: :output
10
+ attr_accessor :appifile
11
+ attr_reader :readme_path, :skeleton_path
12
+ IGNORE_LIST = [".git"]
13
+
14
+ def initialize(template: nil, path: nil)
15
+ raise "Missing template or path keyword" if template.nil? && path.nil?
16
+ @path = File.expand_path("#{Appifier::DEFAULT_TEMPLATES_PATH}/#{template}") if template
17
+ @path = path if path
18
+ @appifile_name = "#{@path}/Appifile"
19
+ @skeleton_path = "#{@path}/skeleton"
20
+ @readme_path = "#{@path}/README.md"
21
+ begin
22
+ @appifile = Appifier::Components::Appifile::new(path: @appifile_name)
23
+ rescue RuntimeError
24
+ raise "Template format error"
25
+ end
26
+ end
27
+
28
+ def readme?
29
+ File.exist? @readme_path
30
+ end
31
+
32
+ def self.validate!(template: nil, path: nil)
33
+ raise "Missing template or path keyword" if template.nil? && path.nil?
34
+ path = File.expand_path("#{Appifier::DEFAULT_TEMPLATES_PATH}/#{template}") if template
35
+ path = path if path
36
+ appifile_name = "#{path}/Appifile"
37
+
38
+ result = Appifier::Components::Appifile.validate!(path: appifile_name)
39
+ IGNORE_LIST.each do |item|
40
+ item_path = "#{path}/#{item}"
41
+ if File.exist? item_path
42
+ FileUtils::rm_rf item_path
43
+ result[:cleaned].push item
44
+ end
45
+ end unless result.include? :error
46
+ result[:error].push "Skeleton path missing" unless File.exist?("#{path}/skeleton")
47
+ result[:warn].push "README.md missing" unless File.exist?("#{path}/README.md")
48
+ result[:status] = :ok
49
+ result[:status] = :partial unless result[:warn].empty?
50
+ result[:status] = :ko unless result[:error].empty?
51
+ return result
52
+ end
53
+
54
+ def self.list
55
+ output.info "List of available templates for user : #{current_user} :"
56
+ template_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
57
+ Dir.glob("#{template_path}/*").map { |item| item.delete_prefix("#{template_path}/") }.each do |template|
58
+ output.item "#{template}"
59
+ end
60
+ end
61
+
62
+ def self.rm(template)
63
+ output.info "Removing template #{template} for user : #{current_user}"
64
+ template_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
65
+ begin
66
+ if File::exist? "#{template_path}/#{template}"
67
+ FileUtils.rm_rf "#{template_path}/#{template}"
68
+ output.ok "Template #{template} deleted of bundle for user #{current_user}"
69
+ else
70
+ raise "Template #{template} not found in bundle for user #{current_user}"
71
+ end
72
+ rescue Errno::ENOENT
73
+ raise "Template #{template} not found in bundle for user #{current_user}"
74
+ end
75
+ end
76
+
77
+ def self.show(template)
78
+ data = Appifier::Components::Template::new(template: template)
79
+ data_template = data.appifile.content[:template]
80
+ output.info "Template #{template} informations"
81
+ output.item "Name : #{data_template[:name]}"
82
+ output.item "Version : #{data_template[:version]}"
83
+ if data_template[:authors]
84
+ output.item "Authors : "
85
+ data_template[:authors].each do |author|
86
+ output.arrow author
87
+ end
88
+ end
89
+ output.item "Description : #{data_template[:description]}" if data_template[:description]
90
+ output.item "Contact : #{data_template[:contact]}" if data_template[:contact]
91
+ output.info "Dataset informations : "
92
+ data_template[:dataset].each do |rule, definition|
93
+ output.item "Rule : #{rule}"
94
+ output.arrow "Description : #{definition[:description]}"
95
+ output.arrow "Default : #{definition[:default]}" if definition[:default]
96
+ output.arrow "Format : #{definition[:format]}"
97
+ end
98
+
99
+ end
100
+
101
+ def self.treeview(template)
102
+ begin
103
+ data = Appifier::Components::Template::new(template: template)
104
+ output.info "Getting tree view for template #{template} : "
105
+ tree = TTY::Tree.new(data.skeleton_path)
106
+ puts tree.render
107
+ rescue RuntimeError
108
+ raise "Template not found"
109
+ end
110
+ end
111
+
112
+ def self.lint(template)
113
+ begin
114
+ res = Appifier::Components::Template.validate!(template: template)
115
+ output.info "List of warnings for template #{template}"
116
+ res[:warn].each do |warn|
117
+ output.warn warn
118
+ end
119
+ rescue RuntimeError
120
+ raise "Template not found"
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -1,20 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appifier
4
- class Configuration
4
+ module Configuration
5
5
  def self.setup(force: false)
6
6
  if File.exist?(File.expand_path(Appifier::DEFAULT_CONFIG_PATH)) && !force
7
7
  puts 'Appifier already configured'
8
8
  else
9
+ FileUtils.rm_rf File.expand_path(Appifier::DEFAULT_PATH)
9
10
  config_file = search_file_in_gem('appifier', 'config/settings.yml')
10
- path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
11
11
  [Appifier::DEFAULT_TEMPLATES_PATH, Appifier::DEFAULT_LOGS_PATH, Appifier::DEFAULT_CONFIG_PATH, Appifier::DEFAULT_DATASETS_PATH].each do |path|
12
12
  FileUtils.mkdir_p File.expand_path(path)
13
13
  end
14
- File.open(File.expand_path("#{Appifier::DEFAULT_LOGS_PATH}/#{Appifier::DEFAULT_LOG_FILENAME}"), 'w') { |file| file.write("# Appifier : beginning of log file") }
14
+ File.open(File.expand_path("#{Appifier::DEFAULT_LOGS_PATH}/#{Appifier::DEFAULT_LOG_FILENAME}"), 'w') { |file| file.write("# Appifier : beginning of log file\n") }
15
15
  FileUtils.cp config_file, File.expand_path(Appifier::DEFAULT_CONFIG_PATH)
16
16
  puts '[OK] Building config folder and initialize settings'
17
17
  end
18
18
  end
19
+
20
+
21
+ class Checker
22
+
23
+ extend Carioca::Injector
24
+ inject service: :output
25
+ inject service: :finisher
26
+
27
+ def self.sanitycheck
28
+ output.info "Checking path for #{current_user} : "
29
+ status = { true => :ok, false => :error }
30
+ [DEFAULT_PATH,DEFAULT_TEMPLATES_PATH,DEFAULT_CONFIG_PATH,DEFAULT_LOGS_PATH,DEFAULT_DATASETS_PATH].each do |path|
31
+ output.send status[File::exist?(File::expand_path(path))], path
32
+ end
33
+ output.info "Checking file for #{current_user} : "
34
+
35
+ ["#{DEFAULT_CONFIG_PATH}/#{DEFAULT_SETTINGS_FILENAME}","#{DEFAULT_LOGS_PATH}/#{DEFAULT_LOG_FILENAME}"].each do |file|
36
+ output.send status[File::exist?(File::expand_path(file))], file
37
+ end
38
+ end
39
+ end
40
+
41
+
19
42
  end
20
43
  end
data/lib/appifier.rb CHANGED
@@ -5,6 +5,11 @@ require 'thot'
5
5
  require 'fileutils'
6
6
  require 'etc'
7
7
 
8
+
9
+ require 'thor'
10
+ require "tty-prompt"
11
+ require 'tty-link'
12
+
8
13
  include Thot
9
14
 
10
15
 
@@ -14,7 +19,7 @@ require 'appifier/helpers/init'
14
19
  module Appifier
15
20
  DEFAULT_PATH = '~/.appifier'
16
21
  DEFAULT_TEMPLATES_PATH = "#{DEFAULT_PATH}/templates"
17
- DEFAULT_CONFIG_PATH = "#{DEFAULT_PATH}/config/"
22
+ DEFAULT_CONFIG_PATH = "#{DEFAULT_PATH}/config"
18
23
  DEFAULT_LOGS_PATH = "#{DEFAULT_PATH}/logs"
19
24
  DEFAULT_DATASETS_PATH = "#{DEFAULT_PATH}/datasets"
20
25
  DEFAULT_LOG_FILENAME = "appifier.log"
@@ -49,13 +54,4 @@ Carioca::Registry.configure do |spec|
49
54
  end
50
55
 
51
56
  require_relative 'appifier/services/init'
52
-
53
- module Appifier
54
- class Application < Carioca::Container
55
- inject service: :configuration
56
- inject service: :i18n
57
- inject service: :terminator
58
- end
59
- end
60
-
61
57
  require_relative 'appifier/components/init'
@@ -0,0 +1,18 @@
1
+ ---
2
+ :template:
3
+ :name: dummy
4
+ :authors:
5
+ - Romain Georges
6
+ - Camille Paquet
7
+ :description: dummy template
8
+ :dataset:
9
+ :appname:
10
+ :description: The application name
11
+ :default: test_application
12
+ :format: \w+
13
+ :actions:
14
+ :deploy: {}
15
+ :run: {}
16
+ :build: {}
17
+ :publish: {}
18
+ :test: {}
Binary file
@@ -1,8 +1,14 @@
1
1
  ---
2
2
  :template:
3
+ :name: dummy
4
+ :version: 1.0
5
+ :authors:
6
+ - Romain Georges
7
+ - Camille Paquet
8
+ :description: a dummy template
3
9
  :dataset:
4
10
  :appname:
5
- :description: The application name
11
+ :description: application name
6
12
  :default: test_application
7
13
  :format: \w+
8
14
  :actions:
@@ -10,3 +16,4 @@
10
16
  :run: {}
11
17
  :build: {}
12
18
  :publish: {}
19
+ :test: {}
@@ -0,0 +1,4 @@
1
+ ## dummy template
2
+
3
+
4
+ this is a test
data/samples/dummy.tgz CHANGED
Binary file
@@ -0,0 +1,19 @@
1
+ ---
2
+ :template:
3
+ :name: dummy
4
+ :version: 1.0
5
+ :authors:
6
+ - Romain Georges
7
+ - Camille Paquet
8
+ :description: a dummy template
9
+ :dataset:
10
+ :appname:
11
+ :description: application name
12
+ :default: test_application
13
+ :format: \w+
14
+ :actions:
15
+ :deploy: {}
16
+ :run: {}
17
+ :build: {}
18
+ :publish: {}
19
+ :test: {}
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Camille Paquet
8
8
  - Romain GEORGES
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-10-24 00:00:00.000000000 Z
12
+ date: 2022-10-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: code_statistics
@@ -165,10 +165,95 @@ dependencies:
165
165
  - - "~>"
166
166
  - !ruby/object:Gem::Version
167
167
  version: 0.23.1
168
+ - !ruby/object:Gem::Dependency
169
+ name: thot
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '1.0'
175
+ type: :runtime
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - "~>"
180
+ - !ruby/object:Gem::Version
181
+ version: '1.0'
182
+ - !ruby/object:Gem::Dependency
183
+ name: git
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - "~>"
187
+ - !ruby/object:Gem::Version
188
+ version: '1.12'
189
+ type: :runtime
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - "~>"
194
+ - !ruby/object:Gem::Version
195
+ version: '1.12'
196
+ - !ruby/object:Gem::Dependency
197
+ name: schash
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - "~>"
201
+ - !ruby/object:Gem::Version
202
+ version: 0.1.2
203
+ type: :runtime
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - "~>"
208
+ - !ruby/object:Gem::Version
209
+ version: 0.1.2
210
+ - !ruby/object:Gem::Dependency
211
+ name: tty-tree
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - "~>"
215
+ - !ruby/object:Gem::Version
216
+ version: 0.4.0
217
+ type: :runtime
218
+ prerelease: false
219
+ version_requirements: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - "~>"
222
+ - !ruby/object:Gem::Version
223
+ version: 0.4.0
224
+ - !ruby/object:Gem::Dependency
225
+ name: tty-markdown
226
+ requirement: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - "~>"
229
+ - !ruby/object:Gem::Version
230
+ version: 0.7.0
231
+ type: :runtime
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - "~>"
236
+ - !ruby/object:Gem::Version
237
+ version: 0.7.0
238
+ - !ruby/object:Gem::Dependency
239
+ name: tty-link
240
+ requirement: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - "~>"
243
+ - !ruby/object:Gem::Version
244
+ version: 0.1.1
245
+ type: :runtime
246
+ prerelease: false
247
+ version_requirements: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - "~>"
250
+ - !ruby/object:Gem::Version
251
+ version: 0.1.1
168
252
  description: 'Appifier : Applications templating and management tools '
169
253
  email:
170
254
  - gems@ultragreen.net
171
255
  executables:
256
+ - app
172
257
  - appifier
173
258
  extensions: []
174
259
  extra_rdoc_files: []
@@ -185,6 +270,7 @@ files:
185
270
  - bin/setup
186
271
  - config/appifier.registry
187
272
  - config/settings.yml
273
+ - exe/app
188
274
  - exe/appifier
189
275
  - lib/appifier.rb
190
276
  - lib/appifier/actors/collector.rb
@@ -193,10 +279,12 @@ files:
193
279
  - lib/appifier/actors/retriever.rb
194
280
  - lib/appifier/cli.rb
195
281
  - lib/appifier/cli/configuration.rb
282
+ - lib/appifier/cli/datasets.rb
196
283
  - lib/appifier/cli/templates.rb
197
284
  - lib/appifier/components/Appifile.rb
285
+ - lib/appifier/components/dataset.rb
198
286
  - lib/appifier/components/init.rb
199
- - lib/appifier/components/templates.rb
287
+ - lib/appifier/components/template.rb
200
288
  - lib/appifier/helpers/archives.rb
201
289
  - lib/appifier/helpers/datasets.rb
202
290
  - lib/appifier/helpers/gem.rb
@@ -206,14 +294,30 @@ files:
206
294
  - lib/appifier/services/init.rb
207
295
  - lib/appifier/setup.rb
208
296
  - lib/appifier/version.rb
297
+ - samples/baddummy.tgz
298
+ - samples/baddummy/Appifile
299
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/.rspec
300
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/Rakefile
301
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/config.ru
302
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/exe/%%APPNAME.downcase%%
303
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/lib/%%APPNAME.downcase%%.rb
304
+ - samples/baddummy/skeleton/%%APPNAME.downcase%%/spec/%%APPNAME.downcase%%_spec.rb
209
305
  - samples/dummy.tgz
210
306
  - samples/dummy/Appifile
307
+ - samples/dummy/README.md
211
308
  - samples/dummy/skeleton/%%APPNAME.downcase%%/.rspec
212
309
  - samples/dummy/skeleton/%%APPNAME.downcase%%/Rakefile
213
310
  - samples/dummy/skeleton/%%APPNAME.downcase%%/config.ru
214
311
  - samples/dummy/skeleton/%%APPNAME.downcase%%/exe/%%APPNAME.downcase%%
215
312
  - samples/dummy/skeleton/%%APPNAME.downcase%%/lib/%%APPNAME.downcase%%.rb
216
313
  - samples/dummy/skeleton/%%APPNAME.downcase%%/spec/%%APPNAME.downcase%%_spec.rb
314
+ - samples/dummy_warn/Appifile
315
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/.rspec
316
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/Rakefile
317
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/config.ru
318
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/exe/%%APPNAME.downcase%%
319
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/lib/%%APPNAME.downcase%%.rb
320
+ - samples/dummy_warn/skeleton/%%APPNAME.downcase%%/spec/%%APPNAME.downcase%%_spec.rb
217
321
  homepage: https://github.com/Ultragreen/appifier
218
322
  licenses:
219
323
  - MIT
@@ -222,7 +326,7 @@ metadata:
222
326
  source_code_uri: https://github.com/Ultragreen/appifier
223
327
  changelog_uri: https://github.com/Ultragreen/appifier
224
328
  rubygems_mfa_required: 'false'
225
- post_install_message:
329
+ post_install_message:
226
330
  rdoc_options: []
227
331
  require_paths:
228
332
  - lib
@@ -237,8 +341,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
341
  - !ruby/object:Gem::Version
238
342
  version: '0'
239
343
  requirements: []
240
- rubygems_version: 3.1.2
241
- signing_key:
344
+ rubygems_version: 3.2.3
345
+ signing_key:
242
346
  specification_version: 4
243
347
  summary: 'Appifier : Applications templating and management tools'
244
348
  test_files: []
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Appifier
4
- module Components
5
- class Templates
6
-
7
- extend Carioca::Injector
8
- inject service: :output
9
-
10
- def self.list
11
- output.info "List of avaible templates for user : #{current_user} :"
12
- template_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
13
- Dir.glob("#{template_path}/*").map { |item| item.delete_prefix("#{template_path}/") }.each do |template|
14
- output.item "#{template}"
15
- end
16
- end
17
-
18
- def self.rm(template)
19
- output.info "Removing template #{template} for user : #{current_user} :"
20
- template_path = File.expand_path(Appifier::DEFAULT_TEMPLATES_PATH)
21
- begin
22
- if File::exist? "#{template_path}/#{template}"
23
- FileUtils.rm_rf "#{template_path}/#{template}"
24
- output.ok "Template #{template} deleted of bundle for user #{current_user}"
25
- else
26
- raise "Template #{template} not found in bundle for user #{current_user}"
27
- end
28
- rescue Errno::ENOENT
29
- raise "Template #{template} not found in bundle for user #{current_user}"
30
- end
31
- end
32
- end
33
- end
34
- end