lad 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +68 -0
- data/Rakefile +2 -0
- data/bin/lad +15 -0
- data/lad.gemspec +22 -0
- data/lib/config.rb +13 -0
- data/lib/console.rb +30 -0
- data/lib/files.rb +28 -0
- data/lib/lad.rb +57 -0
- data/lib/lad/version.rb +3 -0
- data/lib/parser.rb +10 -0
- data/test/test_config.rb +45 -0
- data/test/test_files.rb +63 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 James Hughes
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Strapping Young Lad (or just Lad for short)
|
2
|
+
|
3
|
+
__Strapping Young Lad__ is a tokenised solution template substitution engine. A bit of a mouthful I know but it actually much simpler than it sounds (and hopefully much more useful that you'd think). So what does it do? Well running
|
4
|
+
|
5
|
+
lad /path/to/git/repo MyNewProject
|
6
|
+
|
7
|
+
Will do the following things,
|
8
|
+
|
9
|
+
1. Clone the repo at `path/to/git/repo` into a temporary folder
|
10
|
+
2. Remove the `.git` folder from the repo
|
11
|
+
3. Check for the existence of a `.ladconfig` in the freshly cloned repo
|
12
|
+
- If one exists it loads the config setting
|
13
|
+
- Otherwise it falls back to the defaults
|
14
|
+
4. Replace all instances of the configured token (eg. `__NAME__`) in all files, directories and file contents with the project name (in our case `MyNewProject`)
|
15
|
+
5. Copy the new folder over to your current working directory (`./MyNewProject`)
|
16
|
+
|
17
|
+
What this allows you to do is have a standard project template for pretty much anything (.NET, Ruby, Scala - listen I mean anything - if it a collection of folders and files in a git repo then you set) and create a new instance with a few keystrokes - saving you time and potential RSI.
|
18
|
+
|
19
|
+
SYL was inspired by [WarmuP](https://github.com/chucknorris/warmup) which is itself a gem but it requires you to be running .NET which for a lot of my requirement isn't going to cut it.
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'lad'
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install lad
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
The example above shows you how to use the gem,
|
38
|
+
|
39
|
+
lad <PathToRepo> <ProjectName>
|
40
|
+
|
41
|
+
- `PathToRepo` is the git repository url that will be cloned
|
42
|
+
- `ProjectName` is the name of the project. This will replace the `__NAME__` token in the repository directories, files and contents
|
43
|
+
|
44
|
+
## Configuring the engine via `.ladconfig`
|
45
|
+
|
46
|
+
SYL, once the repository has been cloned will check for the existence of file with the name `.ladconfig` from which it will load the settings. If it doesn't exist the default setting will be applied.
|
47
|
+
|
48
|
+
### Configuration Options
|
49
|
+
|
50
|
+
- `token` - this is the token/indetifier that will be replaced in the template with the name of the project (defaults to `__NAME__`)
|
51
|
+
- `ignore` - a list of extensions that SYL will ignore when it comes to replacing CONTENTS. It will still RENAME the file if the file name includes the token. This allows us to ignore binary files whose contents should not change.
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
60
|
+
|
61
|
+
## Changes
|
62
|
+
|
63
|
+
17 Apr 2012 - Version 0.0.1 released.
|
64
|
+
|
65
|
+
## Roadmap
|
66
|
+
|
67
|
+
- __accept multiple tokens via command line or via interactive shell__
|
68
|
+
- zip support (generate project from zip file)
|
data/Rakefile
ADDED
data/bin/lad
ADDED
data/lad.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/lad/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["James Hughes"]
|
6
|
+
gem.email = ["james@yobriefca.se"]
|
7
|
+
gem.description = %q{Strapping Young Lad: Project Template Bootstrapper}
|
8
|
+
gem.summary = %q{Template generator and token switcher}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "lad"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Lad::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('git')
|
19
|
+
gem.add_dependency('colorize')
|
20
|
+
|
21
|
+
gem.add_development_dependency('minitest')
|
22
|
+
end
|
data/lib/config.rb
ADDED
data/lib/console.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Lad
|
2
|
+
class Console
|
3
|
+
def self.log msg
|
4
|
+
puts msg
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.warn msg
|
8
|
+
puts msg.yellow
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.error msg
|
12
|
+
puts msg.red
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.success msg
|
16
|
+
puts msg.green
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.task msg, &block
|
20
|
+
print " #{msg}".ljust(40)
|
21
|
+
begin
|
22
|
+
block.call
|
23
|
+
puts "OK".green
|
24
|
+
rescue Exception => e
|
25
|
+
puts "XX".red
|
26
|
+
raise e
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/files.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Lad
|
2
|
+
class Files
|
3
|
+
def self.new_filename(item, token, name)
|
4
|
+
item_dir = File.dirname item
|
5
|
+
item_name = File.basename(item).gsub(token, name)
|
6
|
+
|
7
|
+
File.join item_dir, item_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.delete_temporary_files(dir)
|
11
|
+
FileUtils.rm_rf dir if Dir.exists? dir
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.clone_and_orphan(url, dir)
|
15
|
+
Git.clone url, dir
|
16
|
+
FileUtils.rm_rf File.join(dir, '.git')
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.replace_token_in_file(exclusions, file, token, name)
|
20
|
+
if !exclusions.member?(File.extname file)
|
21
|
+
contents = File.read(file).gsub!(token, name)
|
22
|
+
File.open(file, 'w') { |f|
|
23
|
+
f.puts contents
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/lad.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Lad
|
2
|
+
class Bootstrapper
|
3
|
+
def self.execute
|
4
|
+
files_processed = 0
|
5
|
+
dirs_processed = 0
|
6
|
+
options = Arguments.extract
|
7
|
+
dir = File.join(Dir.tmpdir, options[:name])
|
8
|
+
config = {}
|
9
|
+
|
10
|
+
puts '' # insert new line padding
|
11
|
+
|
12
|
+
Console.task 'Cloning git repository' do
|
13
|
+
Files.delete_temporary_files(dir)
|
14
|
+
Files.clone_and_orphan(options[:git_url], dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
Console.task 'Loading configuration' do
|
18
|
+
config = Config.load dir, {
|
19
|
+
token: '__NAME__', # we should support multiple tokens as well, but that appears to be more work
|
20
|
+
ignore: [
|
21
|
+
'.png', '.jpg', '.gif', '.cache', '.suo',
|
22
|
+
'.dll', '.zip', '.nupkg', '.pdb', '.exe'
|
23
|
+
]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
Console.task 'Processing files' do
|
28
|
+
Dir.glob(File.join dir, '**/*').each do |item|
|
29
|
+
if !File.directory?(item)
|
30
|
+
files_processed += 1
|
31
|
+
new_item = Files.new_filename item, config[:token], options[:name]
|
32
|
+
File.rename(item, new_item) if item != new_item
|
33
|
+
|
34
|
+
Files.replace_token_in_file config[:ignore], new_item, config[:token], options[:name]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Console.task 'Processing directories' do
|
40
|
+
Dir.glob(File.join dir, '**/*').each do |item|
|
41
|
+
if File.directory?(item)
|
42
|
+
dirs_processed += 1
|
43
|
+
new_item = Files.new_filename item, config[:token], options[:name]
|
44
|
+
File.rename(item, new_item) if item != new_item
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Console.task 'Moving project files' do
|
50
|
+
File.rename dir, File.join(Dir.pwd, options[:name])
|
51
|
+
end
|
52
|
+
|
53
|
+
Console.success "\n Done processing #{files_processed} file(s)"
|
54
|
+
Console.success " Done processing #{dirs_processed} directories(s)"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/lad/version.rb
ADDED
data/lib/parser.rb
ADDED
data/test/test_config.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require './lib/config' # SUT
|
6
|
+
|
7
|
+
describe Lad::Config do
|
8
|
+
before do
|
9
|
+
@dir = File.join Dir.tmpdir, (0..16).to_a.map{|a| rand(16).to_s(16)}.join
|
10
|
+
@file = File.join @dir, '.ladconfig'
|
11
|
+
@cfg = {
|
12
|
+
'a_property' => 'property_value'
|
13
|
+
}
|
14
|
+
|
15
|
+
FileUtils.rm_rf @dir if Dir.exists? @dir
|
16
|
+
FileUtils.mkdir @dir
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
FileUtils.rm_rf @dir
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'when loading a file that does not exist' do
|
24
|
+
|
25
|
+
before do
|
26
|
+
File.delete @file if File.exists? @file
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns the default values' do
|
30
|
+
Lad::Config.load(@dir, @cfg)['a_property'].must_equal @cfg['a_property']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'when loading a file that does exist' do
|
35
|
+
before do
|
36
|
+
File.open(@file, 'w') do |f|
|
37
|
+
f.puts '''a_property: file_value'''
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the values from that file' do
|
42
|
+
Lad::Config.load(@dir, @cfg)['a_property'].must_equal 'file_value'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/test/test_files.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
require './lib/files' # SUT
|
5
|
+
|
6
|
+
describe Lad::Files do
|
7
|
+
describe 'resolving the new file name' do
|
8
|
+
it 'replaces the token with the name in the filename only' do
|
9
|
+
Lad::Files.new_filename( '/var/tmp/__NAME__/__NAME__.sln', '__NAME__', 'Assertion').must_match '/var/tmp/__NAME__/Assertion.sln'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'will also replace tokens in the bottom most directory of a directory is passed' do
|
13
|
+
Lad::Files.new_filename('/var/tmp/__NAME__/__NAME__', '__NAME__', 'Assertion').must_match '/var/tmp/__NAME__/Assertion'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'will disregard a trailing slash on directory token replacement' do
|
17
|
+
Lad::Files.new_filename('/var/tmp/__NAME__/__NAME__/', '__NAME__', 'Assertion').must_match '/var/tmp/__NAME__/Assertion'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'will do nothing if the bottom most item hasn;t got the token' do
|
21
|
+
Lad::Files.new_filename('/var/tmp/__NAME__/__NAME__/Test.sln', '__NAME__', 'Assertion').must_match '/var/tmp/__NAME__/__NAME__/Test.sln'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'replacing token in files' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
@dir = File.join Dir.tmpdir, (0..16).to_a.map{|a| rand(16).to_s(16)}.join
|
29
|
+
@file = File.join @dir, 'targetfile.txt'
|
30
|
+
@cfg = {
|
31
|
+
'a_property' => 'property_value'
|
32
|
+
}
|
33
|
+
|
34
|
+
FileUtils.rm_rf @dir if Dir.exists? @dir
|
35
|
+
FileUtils.mkdir @dir
|
36
|
+
|
37
|
+
@original = '''
|
38
|
+
lorem lorem __NAME__ lorem lorem
|
39
|
+
lorem __NAME__ lorem lorem lorem
|
40
|
+
'''
|
41
|
+
@expected = '''
|
42
|
+
lorem lorem Assertion lorem lorem
|
43
|
+
lorem Assertion lorem lorem lorem
|
44
|
+
'''
|
45
|
+
|
46
|
+
File.open(@file, 'w') { |f| f.puts @original }
|
47
|
+
end
|
48
|
+
|
49
|
+
after do
|
50
|
+
FileUtils.rm_rf @dir
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'will replace all instances of the token in a file' do
|
54
|
+
Lad::Files.replace_token_in_file [], @file, '__NAME__', 'Assertion'
|
55
|
+
File.open(@file).read.must_match @expected
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'will not replace any tokens if the files extension is excluded' do
|
59
|
+
Lad::Files.replace_token_in_file ['.txt'], @file, '__NAME__', 'Assertion'
|
60
|
+
File.open(@file).read.must_match @original
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- James Hughes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: git
|
16
|
+
requirement: &70226633976000 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70226633976000
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: colorize
|
27
|
+
requirement: &70226633975380 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70226633975380
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: minitest
|
38
|
+
requirement: &70226633974940 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70226633974940
|
47
|
+
description: ! 'Strapping Young Lad: Project Template Bootstrapper'
|
48
|
+
email:
|
49
|
+
- james@yobriefca.se
|
50
|
+
executables:
|
51
|
+
- lad
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- LICENSE
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- bin/lad
|
61
|
+
- lad.gemspec
|
62
|
+
- lib/config.rb
|
63
|
+
- lib/console.rb
|
64
|
+
- lib/files.rb
|
65
|
+
- lib/lad.rb
|
66
|
+
- lib/lad/version.rb
|
67
|
+
- lib/parser.rb
|
68
|
+
- test/test_config.rb
|
69
|
+
- test/test_files.rb
|
70
|
+
homepage: ''
|
71
|
+
licenses: []
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.8.11
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: Template generator and token switcher
|
94
|
+
test_files:
|
95
|
+
- test/test_config.rb
|
96
|
+
- test/test_files.rb
|