foobar_templates 2.0.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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.beader/.gitignore +6 -0
  3. data/.beader/issues/1-support-flexible-template-topologies.yaml +21 -0
  4. data/.beader/issues/2-add-monorepo-support-for-template-discovery-and-generation.yaml +33 -0
  5. data/.beader/issues/3-implement-monorepo-aware-recursive-template-inventory.yaml +29 -0
  6. data/.beader/issues/4-add-leaf-template-selection-with-ambiguity-and-not-found-handling.yaml +30 -0
  7. data/.beader/issues/5-integrate-leaf-template-resolution-into-generation-flow.yaml +30 -0
  8. data/.beader/issues/6-add-monorepo-discovery-and-generation-test-coverage.yaml +31 -0
  9. data/.beader/issues/7-document-monorepo-template-configuration-and-selection.yaml +30 -0
  10. data/.beader/meta.yaml +1 -0
  11. data/.gitignore +16 -0
  12. data/.rspec +2 -0
  13. data/Gemfile +3 -0
  14. data/LICENSE.txt +22 -0
  15. data/README.md +154 -0
  16. data/Rakefile +55 -0
  17. data/bin/foobar_templates +72 -0
  18. data/changelog +107 -0
  19. data/config/config +8 -0
  20. data/foobar_templates.gemspec +33 -0
  21. data/lib/foobar_templates/cli/cheat_sheet.rb +12 -0
  22. data/lib/foobar_templates/cli/cli.rb +3 -0
  23. data/lib/foobar_templates/cli/dir_to_template.rb +120 -0
  24. data/lib/foobar_templates/cli/setup_personal_templates_repo.rb +135 -0
  25. data/lib/foobar_templates/cli/template_generator.rb +462 -0
  26. data/lib/foobar_templates/configurator.rb +99 -0
  27. data/lib/foobar_templates/core/core.rb +9 -0
  28. data/lib/foobar_templates/core/dir_to_template.rb +114 -0
  29. data/lib/foobar_templates/strings.rb +23 -0
  30. data/lib/foobar_templates/template_manager.rb +119 -0
  31. data/lib/foobar_templates/templates/template-test/.vscode/launch.json +0 -0
  32. data/lib/foobar_templates/templates/template-test/foo-bar/keep +0 -0
  33. data/lib/foobar_templates/templates/template-test/foo-bar.rb +16 -0
  34. data/lib/foobar_templates/templates/template-test/foo_bar/keep +0 -0
  35. data/lib/foobar_templates/templates/template-test/foobar.yml +2 -0
  36. data/lib/foobar_templates/templates/template-test/simple_dir/keep +0 -0
  37. data/lib/foobar_templates/templates/template-test/test_confirmed +0 -0
  38. data/lib/foobar_templates/templates/test_template/foo-bar/keep +0 -0
  39. data/lib/foobar_templates/templates/test_template/foo-bar.rb +21 -0
  40. data/lib/foobar_templates/templates/test_template/foo_bar/keep +0 -0
  41. data/lib/foobar_templates/templates/test_template/foobar.yml +2 -0
  42. data/lib/foobar_templates/templates/test_template/simple_dir/keep +0 -0
  43. data/lib/foobar_templates/version.rb +3 -0
  44. data/lib/foobar_templates.rb +151 -0
  45. data/spec/data/variable_manifest_test.rb +21 -0
  46. data/spec/foobar_templates/cli/dir_to_template_spec.rb +153 -0
  47. data/spec/foobar_templates/core/dir_to_template_spec.rb +104 -0
  48. data/spec/foobar_templates_spec.rb +573 -0
  49. data/spec/spec_helper.rb +106 -0
  50. data/spec/template_manager_spec.rb +68 -0
  51. metadata +157 -0
@@ -0,0 +1,23 @@
1
+ module FoobarTemplates
2
+ HELP_MSG = <<-HEREDOC
3
+ Foobar Templates version #{FoobarTemplates::VERSION}
4
+ Use foobar_templates to start a new project folder based on a predefined template.
5
+
6
+ Usage Examples:
7
+
8
+ # Download all my template files (configured in ~/.foobar/config)
9
+ $ foobar_templates --install-public-templates
10
+
11
+ # Create a personal mono-repo template for your projects
12
+ $ foobar_templates --setup-personal-templates
13
+
14
+ # Create a ruby gem project using the built in service template
15
+ $ foobar_templates --template ruby-cli-gem your_project_name
16
+
17
+ # Convert the current directory which represents a working project into a
18
+ # template by replacing project name variants with foo-bar placeholders
19
+ $ cd my_recently_built_project
20
+ $ foobar_templates --copy-to-templates
21
+ HEREDOC
22
+
23
+ end
@@ -0,0 +1,119 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+
4
+ module FoobarTemplates
5
+
6
+ # This class handles the logic for finding templates
7
+ # in the user's dir, the gem's builtin templates
8
+ # (and on the web some day)
9
+ class TemplateManager
10
+
11
+ class << self
12
+
13
+ def internal_template_location() = File.expand_path("#{File.dirname(__FILE__)}/templates")
14
+ def custom_template_location() = File.expand_path("~/.foobar/templates")
15
+ def default_template_name() = "ruby-cli-gem"
16
+
17
+ def get_template_src(options)
18
+ template_name = options[:template] || default_template_name
19
+
20
+ if template_exists_within_repo?(template_name)
21
+ return resolve_template_path(internal_template_location, template_name)
22
+ end
23
+
24
+ custom_src = resolve_template_path(custom_template_location, template_name)
25
+ return custom_src if File.exist?(custom_src)
26
+
27
+ monorepo_match = resolve_monorepo_leaf_template(custom_template_location, template_name)
28
+ return monorepo_match if monorepo_match
29
+
30
+ raise FoobarTemplates::CLIError, "Error: template '#{template_name}' could not be found. Run the below command to list all available templates.\n\n foobar_templates -l"
31
+ end
32
+
33
+ def template_exists_within_repo?(template_name)
34
+ file_in_source?(template_name) || file_in_source?("template-#{template_name}")
35
+ end
36
+
37
+ def resolve_template_path(location, name)
38
+ basic = "#{location}/#{name}"
39
+ prefixed = "#{location}/template-#{name}"
40
+
41
+ return basic if File.exist?(basic)
42
+ return prefixed if File.exist?(prefixed)
43
+
44
+ basic # fallback, even if it doesn't exist, will be caught by get_template_src
45
+ end
46
+
47
+ def resolve_monorepo_leaf_template(root, requested_name)
48
+ monorepo_roots = immediate_subdirectories(root).select { |dir| monorepo_directory?(dir) }
49
+ return nil if monorepo_roots.empty?
50
+
51
+ requested_leaf_name = requested_name.sub(/^template-/, "")
52
+ leaf_paths = monorepo_roots.flat_map { |dir| collect_leaf_templates(dir) }
53
+ matches = leaf_paths.select do |leaf_path|
54
+ File.basename(leaf_path).sub(/^template-/, "") == requested_leaf_name
55
+ end
56
+
57
+ if matches.length > 1
58
+ readable_paths = matches.map { |path| path.sub(/^#{Regexp.escape(root)}\//, "") }.sort.join(", ")
59
+ raise FoobarTemplates::CLIError, "Ambiguous template name '#{requested_name}'. Matching leaf templates: #{readable_paths}. Rename one of the conflicting templates."
60
+ end
61
+
62
+ if matches.empty?
63
+ readable_leaves = leaf_paths.map { |path| File.basename(path).sub(/^template-/, "") }.uniq.sort
64
+ raise FoobarTemplates::CLIError, "Template '#{requested_name}' not found in monorepo leaf templates. Available leaf templates: #{readable_leaves.join(', ')}. Run 'foobar_templates -l' to list all available templates."
65
+ end
66
+
67
+ matches.first
68
+ end
69
+
70
+ def collect_leaf_templates(dir)
71
+ config = load_template_config(dir)
72
+ return [] if config.nil?
73
+
74
+ if config[:monorepo] == true
75
+ immediate_subdirectories(dir).flat_map { |child| collect_leaf_templates(child) }
76
+ else
77
+ [dir]
78
+ end
79
+ end
80
+
81
+ def monorepo_directory?(dir)
82
+ config = load_template_config(dir)
83
+ !config.nil? && config[:monorepo] == true
84
+ end
85
+
86
+ def load_template_config(dir)
87
+ path = File.join(dir, "foobar.yml")
88
+ return nil unless File.exist?(path)
89
+
90
+ raw = YAML.load_file(path, symbolize_names: true)
91
+ raw.is_a?(Hash) ? raw : {}
92
+ rescue StandardError
93
+ {}
94
+ end
95
+
96
+ def immediate_subdirectories(dir)
97
+ return [] unless File.exist?(dir)
98
+
99
+ Dir.children(dir).filter_map do |entry|
100
+ full_path = File.join(dir, entry)
101
+ File.directory?(full_path) ? full_path : nil
102
+ end
103
+ end
104
+
105
+ def find_in_source_paths(target)
106
+ path = "#{__dir__}/templates/#{target}"
107
+ File.exist?(path) ? path : target
108
+ end
109
+
110
+ # Get's path to 'target' from within the gem's "templates" folder
111
+ # within the gem's source
112
+ def file_in_source?(target)
113
+ src_in_source_path = "#{File.dirname(__FILE__)}/templates/#{target}"
114
+ File.exist?(src_in_source_path)
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,16 @@
1
+ This file shows all the variables in one place!
2
+ See "lib/foobar_templates/templates/test_template/>>> foo-bar.rb"
3
+
4
+ >>> foo-bar: foo-bar
5
+ >>> foo_bar: foo_bar
6
+ >>> FooBar: FooBar
7
+ >>> fooBar: fooBar
8
+ >>> FOO_BAR: FOO_BAR
9
+ >>> foo/bar: foo/bar
10
+ >>> foo_bar/foo_bar: foo_bar/foo_bar
11
+ >>> Foo::Bar: Foo::Bar
12
+ >>> FOO_AUTHOR: FOO_AUTHOR
13
+ >>> FOO_EMAIL: FOO_EMAIL
14
+ >>> FOO_GIT_REPO_DOMAIN: FOO_GIT_REPO_DOMAIN
15
+ >>> FOO_GIT_REPO_URL: FOO_GIT_REPO_URL
16
+ >>> FOO_GIT_REPO_PATH: FOO_GIT_REPO_PATH
@@ -0,0 +1,2 @@
1
+ purpose: tool
2
+ language: go
@@ -0,0 +1,21 @@
1
+ This file shows all the variables in one place!
2
+ See "lib/foobar_templates/templates/test_template/>>> foo-bar.rb"
3
+
4
+ >>> foo-bar: foo-bar
5
+ >>> Foo Bar: Foo Bar
6
+ >>> foo_bar: foo_bar
7
+ >>> FooBar: FooBar
8
+ >>> fooBar: fooBar
9
+ >>> FOO_BAR: FOO_BAR
10
+ >>> foo/bar: foo/bar
11
+ >>> foo_bar/foo_bar: foo_bar/foo_bar
12
+ >>> Foo::Bar: Foo::Bar
13
+ >>> FOO_AUTHOR: FOO_AUTHOR
14
+ >>> FOO_EMAIL: FOO_EMAIL
15
+ >>> FOO_GIT_REPO_DOMAIN: FOO_GIT_REPO_DOMAIN
16
+ >>> FOO_GIT_REPO_URL: FOO_GIT_REPO_URL
17
+ >>> FOO_GIT_REPO_PATH: FOO_GIT_REPO_PATH
18
+ >>> FOO_IMAGE_PATH: FOO_IMAGE_PATH
19
+ >>> FOO_REGISTRY_DOMAIN: FOO_REGISTRY_DOMAIN
20
+ >>> FOO_REGISTRY_REPO_PATH: FOO_REGISTRY_REPO_PATH
21
+ >>> FOO_K8S_DOMAIN: FOO_K8S_DOMAIN
@@ -0,0 +1,2 @@
1
+ purpose: tool
2
+ language: go
@@ -0,0 +1,3 @@
1
+ module FoobarTemplates
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,151 @@
1
+ require "foobar_templates/version"
2
+ require "foobar_templates/strings"
3
+ require 'foobar_templates/configurator'
4
+ require 'foobar_templates/template_manager'
5
+
6
+ require 'foobar_templates/core/core'
7
+ require 'foobar_templates/cli/cli'
8
+
9
+ require 'uri'
10
+
11
+ SOURCE_ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
12
+
13
+ module FoobarTemplates
14
+ class CLIError < StandardError; end
15
+
16
+ class << self
17
+
18
+ def version
19
+ FoobarTemplates::VERSION
20
+ end
21
+
22
+ def cheat_sheet
23
+ CLI::CheatSheet.go
24
+ end
25
+
26
+ # lists available templates
27
+ def list
28
+ configurator = Configurator.new
29
+ available_templates = configurator.collect_user_defined_templates
30
+
31
+ available_templates = group_hashes_by_key(available_templates)
32
+ output = convert_grouped_hashes_to_output(available_templates)
33
+
34
+ if output.empty?
35
+ empty_output_msg = "You have no templates. You can install the public example templates with\n"
36
+ empty_output_msg += "the below command:\n\n"
37
+ empty_output_msg += "foobar_templates --install-public-templates"
38
+ return empty_output_msg
39
+ end
40
+
41
+ mark_default_template(output, configurator.default_template)
42
+ end
43
+
44
+ def install_public_templates
45
+ validate_git_is_installed!
46
+ configurator = Configurator.new
47
+ config_file_data = configurator.config_file_data
48
+ puts "Downloading templates from the following locations: \n #{config_file_data['public_templates'].split(" ").join("\n ")}"
49
+ config_file_data['public_templates'].split.each do |url|
50
+ uri = URI.parse(url)
51
+ template_folder_name = File.basename(uri.path).sub(/\.git$/, "")
52
+ if !File.exist?("#{ENV['HOME']}/.foobar/templates/#{template_folder_name}")
53
+ cmd = "cd #{ENV['HOME']}/.foobar/templates && git clone #{url}"
54
+ cmd += " 2> /dev/null" if $test_env
55
+ `#{cmd}`
56
+ else
57
+ puts "Warning: Skipping, template already exists #{ENV['HOME']}/.foobar/templates/#{template_folder_name}"
58
+ end
59
+ end
60
+ end
61
+
62
+ def validate_git_is_installed!
63
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
64
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
65
+ exts.each do |ext|
66
+ exe = File.join(path, "git#{ext}")
67
+ return if File.executable?(exe) && !File.directory?(exe)
68
+ end
69
+ end
70
+
71
+ raise CLIError, "Error: `git` command not found. Please install Git and ensure it's in your PATH."
72
+ end
73
+
74
+ def setup_personal_templates(input: $stdin, output: $stdout)
75
+ CLI::SetupPersonalTemplatesRepo.go(input: input, output: output)
76
+ end
77
+
78
+ def dir_to_template(input: $stdin, output: $stdout)
79
+ CLI::DirToTemplate.go(input: input, output: output)
80
+ end
81
+
82
+ def generate_template(options, gem_name)
83
+ require 'foobar_templates/cli/template_generator'
84
+
85
+ template_generator = CLI::TemplateGenerator.new(options, gem_name).run
86
+ rescue FoobarTemplates::CLIError => e
87
+ msg = e.message
88
+ $stderr.puts msg if msg && !msg.empty? && msg != e.class.name
89
+ end
90
+
91
+ # input: [ { "predefined" => "default" },
92
+ # { "MISC" => "my_thing" },
93
+ # { "prdefined" => "service" }
94
+ # ]
95
+ #
96
+ # output: [ { "predefined" => ["default", "service"] },
97
+ # { "MISC" => ["my_thing"] }
98
+ # ]
99
+ #
100
+ def group_hashes_by_key(available_templates)
101
+ h = {}
102
+ available_templates.each do |hash|
103
+ k = hash.first.first
104
+ v = hash.first.last
105
+ h[k] = [] unless h.has_key?(k)
106
+ h[k] << v
107
+ end
108
+ h
109
+ end
110
+
111
+ # input: [ { "predefined" => ["default", "service"] },
112
+ # { "MISC" => ["my_thing"] }
113
+ # ]
114
+ def convert_grouped_hashes_to_output(available_templates)
115
+ template_list_output = ""
116
+ available_templates.each do |category, template_names|
117
+
118
+ template_list_output << " #{category&.upcase || "UNSPECIFIED"}:\n"
119
+ template_names.each do |el|
120
+ template_list_output << " #{el}\n"
121
+ end
122
+ template_list_output << "\n"
123
+ end
124
+ template_list_output
125
+ end
126
+
127
+ def mark_default_template(output_string, default_template)
128
+ output_string.lines.reverse.map do |l|
129
+ if l.strip == default_template
130
+ l[1]= "*"
131
+ "#{l.chomp} (default)\n"
132
+ else
133
+ l
134
+ end
135
+ end.reverse.join
136
+ end
137
+
138
+ def which(executable)
139
+ if File.file?(executable) && File.executable?(executable)
140
+ executable
141
+ elsif ENV['PATH']
142
+ path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p|
143
+ abs_path = File.join(p, executable)
144
+ File.file?(abs_path) && File.executable?(abs_path)
145
+ end
146
+ path && File.expand_path(executable, path)
147
+ end
148
+ end
149
+
150
+ end
151
+ end
@@ -0,0 +1,21 @@
1
+ This file shows all the variables in one place!
2
+ See "lib/foobar_templates/templates/test_template/foo-bar.rb"
3
+
4
+ foo-bar: good-dog
5
+ Foo Bar: Good Dog
6
+ foo_bar: good_dog
7
+ FooBar: GoodDog
8
+ fooBar: goodDog
9
+ FOO_BAR: GOOD_DOG
10
+ foo/bar: good/dog
11
+ foo_bar/foo_bar: good_dog/good_dog
12
+ Foo::Bar: Good::Dog
13
+ FOO_AUTHOR: Test
14
+ FOO_EMAIL: you@example.com
15
+ FOO_GIT_REPO_DOMAIN: github.com
16
+ FOO_GIT_REPO_URL: https://github.com/Test/good-dog
17
+ FOO_GIT_REPO_PATH: github.com/test/good-dog
18
+ FOO_IMAGE_PATH: test/good-dog
19
+ FOO_REGISTRY_DOMAIN: my-registry.example.com
20
+ FOO_REGISTRY_REPO_PATH: my-registry.example.com/test/good-dog
21
+ FOO_K8S_DOMAIN: my-k8s.example.com
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ module FoobarTemplates::CLI
4
+ describe DirToTemplate do
5
+ before :each do
6
+ @mocked_home = "/tmp/foobar_templates_mock_home"
7
+ @template_root = "#{@mocked_home}/.foobar/templates"
8
+ @dst_dir = "/tmp/foobar_templates_dst_dir"
9
+ @personal_repo = "#{@template_root}/templates-test" # name from reset_test_env
10
+
11
+ reset_test_env
12
+ FileUtils.cd(@dst_dir)
13
+ @initial_dir = FileUtils.pwd
14
+ end
15
+
16
+ after :each do
17
+ FileUtils.cd(@initial_dir)
18
+ end
19
+
20
+ def init_project(name, files: {})
21
+ project_dir = "#{@dst_dir}/#{name}"
22
+ FileUtils.mkdir_p(project_dir)
23
+ FileUtils.cd(project_dir)
24
+ files.each do |rel, contents|
25
+ FileUtils.mkdir_p(File.dirname(rel)) unless File.dirname(rel) == "."
26
+ File.write(rel, contents)
27
+ end
28
+ `git init -q && git add -A && git commit -q -m init`
29
+ project_dir
30
+ end
31
+
32
+ it "errors when no personal templates repo exists" do
33
+ init_project("cool-app", files: { "main.rb" => "puts 'hi'\n" })
34
+
35
+ out = StringIO.new
36
+ expect { DirToTemplate.go(input: StringIO.new(""), output: out) }.to raise_error(FoobarTemplates::CLIError)
37
+ expect(out.string).to include "Unable to convert to template, no personal templates repo exists."
38
+ expect(out.string).to include "foobar_templates --setup-personal-templates"
39
+ end
40
+
41
+ it "copies the project into the personal templates repo and runs the rename transform" do
42
+ FileUtils.mkdir_p(@personal_repo)
43
+ project_dir = init_project("cool-app", files: {
44
+ "main.rb" => "class CoolApp; end\nNAME = 'cool-app'\nMOD = 'cool_app'\nENV_VAR = 'COOL_APP_HOME'\n",
45
+ ".gitignore" => "ignored.log\n",
46
+ "lib/cool_app.rb" => "module CoolApp; end\n",
47
+ })
48
+ File.write("#{project_dir}/ignored.log", "should not be copied")
49
+
50
+ out = StringIO.new
51
+ DirToTemplate.go(input: StringIO.new(""), output: out)
52
+
53
+ dest = "#{@personal_repo}/cool-app"
54
+ expect(File).to exist("#{dest}/main.rb")
55
+ expect(File).to exist("#{dest}/lib/cool_app.rb")
56
+ expect(File).to exist("#{dest}/.gitignore")
57
+ expect(File).not_to exist("#{dest}/ignored.log")
58
+ expect(File).not_to exist("#{dest}/.git")
59
+
60
+ content = File.read("#{dest}/main.rb")
61
+ expect(content).to include "FooBar"
62
+ expect(content).to include "foo-bar"
63
+ expect(content).to include "foo_bar"
64
+ expect(content).to include "FOO_BAR"
65
+ expect(content).not_to include "cool-app"
66
+ expect(content).not_to include "CoolApp"
67
+
68
+ expect(File.read("#{dest}/foobar.yml")).to include "category: misc"
69
+
70
+ expect(out.string).to include "Template created at: #{dest}"
71
+ expect(out.string).to match(/clean|review|remove/i)
72
+ end
73
+
74
+ it "preserves an existing foobar.yml in the source project" do
75
+ FileUtils.mkdir_p(@personal_repo)
76
+ init_project("cool-app", files: {
77
+ "foobar.yml" => "category: backend\n",
78
+ "main.rb" => "puts 'hi'\n",
79
+ })
80
+
81
+ DirToTemplate.go(input: StringIO.new(""), output: StringIO.new)
82
+
83
+ dest = "#{@personal_repo}/cool-app"
84
+ expect(File.read("#{dest}/foobar.yml")).to include "category: backend"
85
+ end
86
+
87
+ it "prompts for a custom template folder name and category" do
88
+ FileUtils.mkdir_p(@personal_repo)
89
+ init_project("cool-app", files: {
90
+ "main.rb" => "class CoolApp; end\nNAME = 'cool-app'\n",
91
+ "lib/cool_app.rb" => "module CoolApp; end\n",
92
+ })
93
+
94
+ out = StringIO.new
95
+ DirToTemplate.go(input: StringIO.new("my-cool-template\nbackend\n"), output: out)
96
+
97
+ dest = "#{@personal_repo}/my-cool-template"
98
+ expect(File).to exist("#{dest}/main.rb")
99
+ expect(File.read("#{dest}/foobar.yml")).to include "category: backend"
100
+
101
+ content = File.read("#{dest}/main.rb")
102
+ expect(content).to include "FooBar"
103
+ expect(content).to include "foo-bar"
104
+ expect(content).not_to include "cool-app"
105
+ expect(content).not_to include "CoolApp"
106
+ end
107
+
108
+ it "defaults the category prompt to the existing foobar.yml category" do
109
+ FileUtils.mkdir_p(@personal_repo)
110
+ init_project("cool-app", files: {
111
+ "foobar.yml" => "category: backend\n",
112
+ "main.rb" => "puts 'hi'\n",
113
+ })
114
+
115
+ out = StringIO.new
116
+ DirToTemplate.go(input: StringIO.new("\n\n"), output: out)
117
+
118
+ expect(out.string).to include "Category [backend]:"
119
+ expect(File.read("#{@personal_repo}/cool-app/foobar.yml")).to include "category: backend"
120
+ end
121
+
122
+ it "rejects invalid template folder names" do
123
+ FileUtils.mkdir_p(@personal_repo)
124
+ init_project("cool-app", files: { "main.rb" => "x" })
125
+
126
+ out = StringIO.new
127
+ expect {
128
+ DirToTemplate.go(input: StringIO.new("bad/name\n"), output: out)
129
+ }.to raise_error(FoobarTemplates::CLIError)
130
+ expect(out.string).to include "invalid template folder name"
131
+ end
132
+
133
+ it "aborts if a template with the same basename already exists" do
134
+ FileUtils.mkdir_p("#{@personal_repo}/cool-app")
135
+ init_project("cool-app", files: { "main.rb" => "x" })
136
+
137
+ out = StringIO.new
138
+ expect { DirToTemplate.go(input: StringIO.new(""), output: out) }.to raise_error(FoobarTemplates::CLIError)
139
+ expect(out.string).to include "already exists at #{@personal_repo}/cool-app"
140
+ end
141
+
142
+ it "errors when not run inside a git repository" do
143
+ FileUtils.mkdir_p(@personal_repo)
144
+ project_dir = "#{@dst_dir}/no-git-app"
145
+ FileUtils.mkdir_p(project_dir)
146
+ FileUtils.cd(project_dir)
147
+
148
+ out = StringIO.new
149
+ expect { DirToTemplate.go(input: StringIO.new(""), output: out) }.to raise_error(FoobarTemplates::CLIError)
150
+ expect(out.string).to include "must be run from within a git repository"
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+ require 'find'
3
+
4
+ module FoobarTemplates::Core
5
+ describe DirToTemplate do
6
+ before :each do
7
+ @mocked_home = "/tmp/foobar_templates_mock_home"
8
+ @template_root = "#{@mocked_home}/.foobar/templates"
9
+ @dst_dir = "/tmp/foobar_templates_dst_dir"
10
+
11
+ reset_test_env
12
+ FileUtils.chdir(@dst_dir)
13
+ @initial_dir = FileUtils.pwd
14
+ end
15
+
16
+ after :each do
17
+ FileUtils.cd(@initial_dir)
18
+ end
19
+
20
+ it 'will process the expected files and ignore the ones that should be ignored' do
21
+ template_dir = create_user_defined_template(category: "wizardly_tools")
22
+
23
+ gitignored_file = "something.toignore"
24
+
25
+ # Setup test template
26
+ FileUtils.cd(template_dir)
27
+ FileUtils.touch("#{template_dir}/README.md")
28
+ FileUtils.touch("#{template_dir}/#{gitignored_file}")
29
+ File.write("#{template_dir}/.gitignore", gitignored_file)
30
+ `git init`
31
+
32
+ files_changed = DirToTemplate.🧙🪄! Find.find("."), dry_run: true
33
+
34
+ expect(files_changed[0]).to eq "Processed: ./README.md"
35
+ expect(File).to exist "#{template_dir}/.gitignore"
36
+ expect(files_changed.count).to eq 1
37
+ end
38
+
39
+ it 'conducts text replacements of package name variants' do
40
+ template_dir = create_user_defined_template(category: "wizardly_tools")
41
+ template_name = "cool-app"
42
+
43
+ FileUtils.cd(template_dir)
44
+ File.write("#{template_dir}/main.go", "package cool_app\nconst Name = \"cool-app\"\nconst ENV = \"COOL_APP_ENV\"\nclass CoolApp\n def coolApp\n end\nend\n")
45
+ File.write("#{template_dir}/.gitignore", "")
46
+ `git init`
47
+
48
+ DirToTemplate.🧙🪄! Find.find("."), template_name: template_name
49
+
50
+ content = File.read("#{template_dir}/main.go")
51
+ expect(content).to include 'foo_bar'
52
+ expect(content).to include 'foo-bar'
53
+ expect(content).to include 'FOO_BAR'
54
+ expect(content).to include 'FooBar'
55
+ expect(content).to include 'fooBar'
56
+ expect(content).not_to include 'cool-app'
57
+ expect(content).not_to include 'cool_app'
58
+ expect(content).not_to include 'COOL_APP'
59
+ expect(content).not_to include 'CoolApp'
60
+ expect(content).not_to include 'coolApp'
61
+ end
62
+
63
+ it 'reverse-substitutes FOO_* placeholder values from git config and foobar_templates config' do
64
+ template_dir = create_user_defined_template(category: "wizardly_tools")
65
+ template_name = "good-dog"
66
+
67
+ FileUtils.cd(template_dir)
68
+ manifest = <<~CONTENT
69
+ author: Test
70
+ email: you@example.com
71
+ repo_domain: github.com
72
+ repo_url: https://github.com/Test/good-dog
73
+ repo_path: github.com/test/good-dog
74
+ image_path: test/good-dog
75
+ registry_domain: my-registry.example.com
76
+ registry_repo_path: my-registry.example.com/test/good-dog
77
+ k8s_domain: my-k8s.example.com
78
+ CONTENT
79
+ File.write("#{template_dir}/manifest.txt", manifest)
80
+ File.write("#{template_dir}/.gitignore", "")
81
+ `git init`
82
+
83
+ DirToTemplate.🧙🪄! Find.find("."), template_name: template_name
84
+
85
+ content = File.read("#{template_dir}/manifest.txt")
86
+ expect(content).to include 'FOO_AUTHOR'
87
+ expect(content).to include 'FOO_EMAIL'
88
+ expect(content).to include 'FOO_GIT_REPO_DOMAIN'
89
+ expect(content).to include 'FOO_GIT_REPO_URL'
90
+ expect(content).to include 'FOO_GIT_REPO_PATH'
91
+ expect(content).to include 'FOO_IMAGE_PATH'
92
+ expect(content).to include 'FOO_REGISTRY_DOMAIN'
93
+ expect(content).to include 'FOO_REGISTRY_REPO_PATH'
94
+ expect(content).to include 'FOO_K8S_DOMAIN'
95
+
96
+ expect(content).not_to include 'you@example.com'
97
+ expect(content).not_to include 'github.com'
98
+ expect(content).not_to include 'my-registry.example.com'
99
+ expect(content).not_to include 'my-k8s.example.com'
100
+ expect(content).not_to include 'good-dog'
101
+ expect(content).not_to include 'good_dog'
102
+ end
103
+ end
104
+ end