skeletor 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ Skeletor
2
+ ========
3
+
4
+ Skeletor is a Ruby Library for setting up quick project skeletons based on code templates.
5
+
6
+ Contributing to Skeletor
7
+ ------------------------
8
+
9
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
10
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
11
+ * Fork the project
12
+ * Start a feature/bugfix branch
13
+ * Commit and push until you are happy with your contribution
14
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
15
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
16
+
17
+ Copyright
18
+ ---------
19
+
20
+ Copyright (c) 2011 OiNutter. See LICENSE.txt for
21
+ further details.
22
+
data/bin/skeletor ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "skeletor"
4
+ require "optparse"
5
+
6
+ Skeletor::CLI.start
data/lib/skeletor.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'skeletor/version'
2
+
3
+ module Skeletor
4
+ autoload :Skeletons, 'skeletor/skeletons'
5
+ autoload :Tasks, 'skeletor/tasks'
6
+ autoload :Builder, 'skeletor/builder'
7
+ autoload :Includes, 'skeletor/includes'
8
+ autoload :CLI, 'skeletor/cli'
9
+ end
@@ -0,0 +1,129 @@
1
+ require 'fileutils'
2
+
3
+ module Skeletor
4
+
5
+ class Builder
6
+
7
+ def initialize(project,template,path)
8
+
9
+ @project = project
10
+ @template_name = File.basename(template).gsub('.yml','')
11
+ @template = Skeletons::Skeleton.new(template)
12
+ @path = path
13
+
14
+ end
15
+
16
+ def build()
17
+
18
+ #check dir exists, if not, make it
19
+ if(!File.exists?(@path))
20
+ Dir.mkdir(@path)
21
+ end
22
+
23
+ #build directory structure
24
+ puts 'Building directory structure'
25
+ build_skeleton(@template.directory_structure)
26
+
27
+ #execute build tasks
28
+ puts 'Running build tasks'
29
+ execute_tasks(@template.tasks,@template.path)
30
+
31
+ puts 'Skeleton built'
32
+
33
+ end
34
+
35
+ def build_skeleton(dirs,path=@path)
36
+
37
+ dirs.each{
38
+ |node|
39
+
40
+ if node.kind_of?(Hash) && !node.empty?()
41
+ node.each_pair{
42
+ |dir,content|
43
+
44
+ puts 'Creating directory ' + File.join(path,dir)
45
+ Dir.mkdir(File.join(path,dir))
46
+
47
+ if content.kind_of?(Array) && !content.empty?()
48
+ build_skeleton(content,File.join(path,dir))
49
+ end
50
+
51
+ }
52
+ elsif node.kind_of?(Array) && !node.empty?()
53
+ node.each{
54
+ |file|
55
+
56
+ write_file(file,path)
57
+
58
+ }
59
+ end
60
+
61
+ }
62
+
63
+ end
64
+
65
+ def self.clean(path=@path)
66
+
67
+ puts 'Cleaning directory of files and folders'
68
+ start_dir = Dir.new(path)
69
+
70
+ start_dir.each{
71
+ |dir|
72
+
73
+ if dir != '.' && dir != '..'
74
+ FileUtils.rm_r File.join(path,dir), {:secure=>true}
75
+ end
76
+
77
+ }
78
+ puts 'Directory cleaned'
79
+
80
+ end
81
+
82
+ def write_file(file,path)
83
+
84
+ #if a pre-existing file is specified in the includes list, copy that, if not write a blank file
85
+ if @template.includes.has_key?(file)
86
+ begin
87
+ Includes.copy_include(@template.includes[file],File.join(path,file),@template.path)
88
+ rescue TypeError => e
89
+ puts e.message
90
+ exit
91
+ end
92
+ else
93
+ puts 'Creating blank file: ' + File.join(path,file)
94
+ File.open(File.join(path,file),'w')
95
+ end
96
+
97
+ end
98
+
99
+ def execute_tasks(tasks,template_path)
100
+
101
+ if File.exists?(File.expand_path(File.join(template_path,'tasks.rb')))
102
+ load File.expand_path(File.join(template_path,'tasks.rb'))
103
+ end
104
+
105
+ tasks.each{
106
+ |task|
107
+
108
+ puts 'Running Task: ' + task
109
+
110
+ task = task.gsub('<skeleton_path>',@path)
111
+ task = task.gsub('<skeleton_project>',@project)
112
+ task = task.gsub('<skelton_template>',@template_name)
113
+
114
+ options = task.split(', ')
115
+ action = options.slice!(0)
116
+
117
+ if(Tasks.respond_to?(action))
118
+ Tasks.send action, options.join(', ')
119
+ else
120
+ send action, options.join(', ')
121
+ end
122
+
123
+ }
124
+
125
+ end
126
+
127
+ end
128
+
129
+ end
@@ -0,0 +1,40 @@
1
+ require 'thor'
2
+
3
+ module Skeletor
4
+
5
+ class CLI < Thor
6
+
7
+ desc "build TEMPLATE [options]", "Build project skeleton from TEMPLATE"
8
+ method_option :directory,
9
+ :aliases => "-d",
10
+ :desc => "Sets the target directory. Defaults to current directory."
11
+ method_option :project,
12
+ :aliases => "-p",
13
+ :desc => "Sets the project name. Defaults to current directory name."
14
+ def build(template)
15
+ path = options[:directory] || Dir.pwd
16
+ project = options[:project] || File.basename(path)
17
+
18
+ skeleton = Builder.new(project,template,path)
19
+ skeleton.build
20
+ end
21
+
22
+ desc "clean [options]" ,"Clean directory"
23
+ method_option :directory,
24
+ :aliases => "-d",
25
+ :desc => "Sets the target directory. Defaults to current directory"
26
+ def clean
27
+ path = options[:directory] || Dir.pwd
28
+ Builder.clean path
29
+ end
30
+
31
+ desc "validate TEMPLATE" ,"Checks TEMPLATE is a valid YAML file and matches the required schema."
32
+ def validate(template)
33
+ skeleton = Skeletons::Loader.loadTemplate(template)
34
+ validator = Skeletons::Validator.new(skeleton)
35
+ validator.validate()
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,49 @@
1
+ require 'uri'
2
+
3
+ autoload :HTTP, 'skeletor/protocols/http'
4
+ autoload :HTTPS, 'skeletor/protocols/https'
5
+
6
+ module Skeletor
7
+
8
+ class Includes
9
+
10
+ PROTOCOL_PATTERN = /(?:([a-z][\w-]+):(?:\/{1,3}|[a-z0-9%]))/
11
+ SUPPORTED_PROTOCOLS = ['http','https']
12
+
13
+ def self.copy_include(include,target,path)
14
+
15
+ #if include path includes a protocol. Load from that
16
+ matches = PROTOCOL_PATTERN.match(include).to_a
17
+ if !matches.empty?
18
+ protocol = matches[1].to_s.downcase
19
+ if !SUPPORTED_PROTOCOLS.find_index(protocol).nil?
20
+ case protocol
21
+ when 'http'
22
+ content = HTTP.get URI.parse(include)
23
+ when 'https'
24
+ uri = URI.parse(include)
25
+ http = HTTPS.new uri.host,443
26
+ http.use_ssl = true
27
+ req = HTTPS::Get.new uri.path
28
+ request = http.request(req)
29
+ content = request.body
30
+ else
31
+ raise TypeError, 'Unsupported protocol ' + protocol + ' for remote file. Only the following are supported: ' + SUPPORTED_PROTOCOLS.join(', ')
32
+ end
33
+ puts 'Copying remote file ' + include + ' to ' + target
34
+ else
35
+ raise TypeError, 'Unsupported protocol for remote file. Only the following are supported: ' + SUPPORTED_PROTOCOLS.join(', ')
36
+ end
37
+ else
38
+ puts 'Copying ' + include + ' from template directory to ' + target
39
+ file = File.open(File.join(path,include))
40
+ content = file.gets
41
+ end
42
+
43
+ File.open(target,'w'){|f| f.write(content)}
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,2 @@
1
+ require 'net/http'
2
+ HTTP = Net::HTTP
@@ -0,0 +1,3 @@
1
+ #require 'always_verify_ssl_certificates'
2
+ require 'net/https'
3
+ HTTPS = Net::HTTP
@@ -0,0 +1,9 @@
1
+ module Skeletor
2
+
3
+ module Skeletons
4
+ autoload :Loader, 'skeletor/skeletons/loader'
5
+ autoload :Validator, 'skeletor/skeletons/validator'
6
+ autoload :Skeleton, 'skeletor/skeletons/skeleton'
7
+ end
8
+
9
+ end
@@ -0,0 +1,47 @@
1
+ require 'YAML'
2
+
3
+ module Skeletor
4
+
5
+ module Skeletons
6
+
7
+ class Loader
8
+
9
+ TEMPLATE_PATH = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), "templates"))
10
+ USER_TEMPLATE_PATH = File.expand_path('~/.skeletor/templates')
11
+
12
+ def self.loadTemplate(template)
13
+
14
+ puts 'Loading Template - ' + template
15
+
16
+ if File.exists?(template) && !File.directory?(template)
17
+ skeleton = YAML.load_file(template)
18
+ path = File.dirname(template)
19
+ elsif File.exists?(File.join(template,File.basename(template) + '.yml'))
20
+ skeleton = YAML.load_file(File.join(template,File.basename(template) + '.yml'))
21
+ path = template
22
+ elsif File.exists?(File.join(USER_TEMPLATE_PATH,template,template+'.yml'))
23
+ skeleton = YAML.load_file(File.join(USER_TEMPLATE_PATH,template,template+'.yml'))
24
+ path = File.join(USER_TEMPLATE_PATH,template)
25
+ elsif File.exists?(File.join(TEMPLATE_PATH,template,template+'.yml'))
26
+ skeleton = YAML.load_file(File.join(TEMPLATE_PATH,template,template+'.yml'))
27
+ path = File.join(TEMPLATE_PATH,template)
28
+ else
29
+ raise LoadError, 'Error: Template File ' + File.basename(template) + ' Could Not Be Found'
30
+ end
31
+
32
+ puts 'Template ' + File.basename(template) + '.yml loaded from ' + path
33
+ if skeleton
34
+ skeleton['path'] = path
35
+ else
36
+ raise LoadError, 'Error: Template could not be parsed as vald YAML'
37
+ end
38
+
39
+ return skeleton
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,47 @@
1
+ module Skeletor
2
+
3
+ module Skeletons
4
+
5
+ class Skeleton
6
+
7
+ def initialize(template)
8
+
9
+ begin
10
+ @template = Loader.loadTemplate(template)
11
+ validator = Validator.new(@template)
12
+ if validator.validate
13
+ @directory_structure = @template["directory_structure"] || []
14
+ @tasks = @template["tasks"] || {}
15
+ @includes = @template["includes"] || {}
16
+ @path = @template["path"]
17
+ else
18
+ exit
19
+ end
20
+ rescue LoadError => e
21
+ puts e.message
22
+ exit
23
+ end
24
+
25
+ end
26
+
27
+ def directory_structure
28
+ @directory_structure
29
+ end
30
+
31
+ def tasks
32
+ @tasks
33
+ end
34
+
35
+ def includes
36
+ @includes
37
+ end
38
+
39
+ def path
40
+ @path
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,169 @@
1
+ module Skeletor
2
+
3
+ module Skeletons
4
+
5
+ class Validator
6
+
7
+ SCHEMA_FILE = File.join Skeletons::Loader::TEMPLATE_PATH,'template-schema.yml'
8
+
9
+ def initialize(template,schema=SCHEMA_FILE)
10
+ @errors = []
11
+ @template = template
12
+ @schema = Loader.loadTemplate(schema)
13
+ @types = @schema['types'] || {}
14
+ end
15
+
16
+ def validate()
17
+ failed = []
18
+
19
+ @schema['sections'].each{
20
+ |section|
21
+
22
+ #check required sections are there
23
+ if (section['required'] && !@template.has_key?(section['name']))
24
+ @errors.push('Error: missing required section - ' + section['name'])
25
+ failed.push(section['name'])
26
+ elsif @template.has_key?(section['name'])
27
+ node = @template[section['name']]
28
+ validated = match_node(node,section,section['name'])
29
+ if(!validated)
30
+ failed.push(section['name'])
31
+ end
32
+ end
33
+
34
+ }
35
+
36
+ puts 'Result: ' + (failed.empty? ? 'Validated Successfully!' : 'Validation Failed!')
37
+
38
+ if !failed.empty? && !@errors.empty?
39
+ puts 'Validation Failed with ' + @errors.count.to_s + ' errors';
40
+ puts ''
41
+ @errors.each{
42
+ |error|
43
+ puts error
44
+ }
45
+ return false
46
+ else
47
+ return true
48
+ end
49
+
50
+ end
51
+
52
+ def match_node(node,expected,label)
53
+
54
+ #check type
55
+ if !check_type(node,expected['type'],label,expected['ok_empty'])
56
+ return false
57
+ end
58
+
59
+ if (node.kind_of?(Hash) || node.kind_of?(Array))
60
+
61
+ if node.empty? && !expected['ok_empty']
62
+ @errors.push('Error: node ' + label + ' cannot be empty')
63
+ return false
64
+ elsif !node.empty? && expected.has_key?('accepts')
65
+ valid_content = false
66
+
67
+ if node.kind_of?(Hash)
68
+ matched = []
69
+ unmatched = []
70
+ node.each_pair{
71
+ |key,value|
72
+
73
+ expected['accepts'].each{
74
+ |accepts|
75
+
76
+ result = check_type(value,accepts,key)
77
+
78
+ if result
79
+ matched.push(key)
80
+ if !unmatched.find_index(key).nil?
81
+ unmatched.slice(unmatched.find_index(key))
82
+ end
83
+ break
84
+ else
85
+ unmatched.push(key)
86
+ end
87
+
88
+ }
89
+
90
+ }
91
+
92
+ if(matched.count==node.count)
93
+ valid_content = true
94
+ else
95
+ unmatched.each{
96
+ |node|
97
+
98
+ @errors.push('Error: node ' + node + ' is not of an accepted type. Should be one of ' + expected['accepts'].join(', '))
99
+ }
100
+ end
101
+
102
+ elsif node.kind_of?(Array)
103
+ matched = []
104
+ unmatched = []
105
+ node.each_index{
106
+ |n|
107
+
108
+ expected['accepts'].each{
109
+ |accepts|
110
+
111
+ key = label + '[' + n.to_s + ']'
112
+ result = check_type(node[n],accepts,key)
113
+
114
+ if result
115
+
116
+ matched.push(key)
117
+ if !unmatched.find_index(key).nil?
118
+ unmatched.slice(unmatched.find_index(key))
119
+ end
120
+ break
121
+ else
122
+ unmatched.push(key)
123
+ end
124
+
125
+ }
126
+ }
127
+
128
+ if(matched.count==node.count)
129
+ valid_content = true
130
+ else
131
+ unmatched.each{
132
+ |node|
133
+
134
+ @errors.push('Error: node ' + node + ' is not of an accepted type. Should be one of ' + expected['accepts'].join(', '))
135
+ }
136
+ end
137
+
138
+ end
139
+
140
+ if !valid_content
141
+ @errors.push('Error: node ' + label + ' contains an unaccepted type.')
142
+ return false
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ return true
149
+
150
+ end
151
+
152
+ def check_type(node,expected_type,label,accept_nil = false)
153
+
154
+ valid_type = true;
155
+ if(@types.has_key?(expected_type))
156
+ valid_type = match_node(node,@types[expected_type],label)
157
+ elsif node.class.to_s != expected_type && !(node.kind_of?(NilClass) && (expected_type=='empty' || accept_nil))
158
+ valid_type = false
159
+ end
160
+
161
+ return valid_type
162
+
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+
169
+ end
@@ -0,0 +1,16 @@
1
+ module Skeletor
2
+
3
+ class Tasks
4
+
5
+ def self.git_init(path)
6
+ system "cd " + path + '
7
+ git init'
8
+ end
9
+
10
+ def self.capify(path)
11
+ system "capify " + path
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,14 @@
1
+ directory_structure:
2
+ -
3
+ src:
4
+ lib:
5
+ test:
6
+ -
7
+ functional:
8
+ -
9
+ - foo
10
+
11
+ unit:
12
+ -
13
+ - README.md
14
+ - LICENSE
@@ -0,0 +1,38 @@
1
+ sections:
2
+ - name: directory_structure
3
+ required: yes
4
+ type: Array
5
+ ok_empty: yes
6
+ accepts:
7
+ - directory_list
8
+ - file_list
9
+ - name: tasks
10
+ required: no
11
+ type: Array
12
+ accepts:
13
+ - String
14
+ - name: includes
15
+ required: no
16
+ type: Hash
17
+ accepts:
18
+ - String
19
+ types:
20
+ directory_list:
21
+ type: Hash
22
+ ok_empty: no
23
+ accepts:
24
+ - directory
25
+ file_list:
26
+ type: Array
27
+ ok_empty: no
28
+ accepts:
29
+ - file
30
+ directory:
31
+ type: Array
32
+ ok_empty: yes
33
+ accepts:
34
+ - empty
35
+ - directory_list
36
+ - file_list
37
+ file:
38
+ type: String
@@ -0,0 +1,3 @@
1
+ module Skeletor
2
+ VERSION="0.6.1"
3
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skeletor
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 6
8
+ - 1
9
+ version: 0.6.1
10
+ platform: ruby
11
+ authors:
12
+ - Will McKenzie
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-09-25 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thor
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Skeletor is a Ruby Gem for creating skeleton directory structures based on a YAML template.
34
+ email:
35
+ - will@oinutter.co.uk
36
+ executables:
37
+ - skeletor
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - README.md
44
+ - lib/skeletor/builder.rb
45
+ - lib/skeletor/cli.rb
46
+ - lib/skeletor/includes.rb
47
+ - lib/skeletor/protocols/http.rb
48
+ - lib/skeletor/protocols/https.rb
49
+ - lib/skeletor/skeletons/loader.rb
50
+ - lib/skeletor/skeletons/skeleton.rb
51
+ - lib/skeletor/skeletons/validator.rb
52
+ - lib/skeletor/skeletons.rb
53
+ - lib/skeletor/tasks.rb
54
+ - lib/skeletor/version.rb
55
+ - lib/skeletor.rb
56
+ - bin/skeletor
57
+ - lib/skeletor/templates/js-lib/js-lib.yml
58
+ - lib/skeletor/templates/template-schema.yml
59
+ has_rdoc: true
60
+ homepage: http://github.com/OiNutter/skeletor
61
+ licenses:
62
+ - MIT
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirements: []
85
+
86
+ rubyforge_project: skeletor
87
+ rubygems_version: 1.3.7
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Gem for creating project skeletons based on YAML templates
91
+ test_files: []
92
+