quik 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{HISTORY.md → CHANGELOG.md} +3 -3
- data/LICENSE.md +116 -0
- data/Manifest.txt +30 -29
- data/README.md +133 -131
- data/Rakefile +33 -34
- data/bin/qk +5 -5
- data/bin/quik +5 -5
- data/lib/quik.rb +55 -44
- data/lib/quik/builder.rb +96 -96
- data/lib/quik/catalog.rb +73 -56
- data/lib/quik/cli/main.rb +213 -179
- data/lib/quik/cli/opts.rb +33 -33
- data/lib/quik/colors.rb +148 -147
- data/lib/quik/config.rb +60 -60
- data/lib/quik/merger.rb +207 -208
- data/lib/quik/package.rb +116 -115
- data/lib/quik/version.rb +24 -24
- data/lib/quik/wizard.rb +88 -88
- data/test/data/gem-starter-template/Manifest.txt +9 -9
- data/test/data/gem-starter-template/README.md +22 -22
- data/test/data/gem-starter-template/lib/__filename__/version.rb +12 -12
- data/test/helper.rb +18 -22
- data/test/test_colors.rb +39 -39
- data/test/test_config.rb +35 -35
- data/test/test_merger.rb +35 -35
- data/test/test_package.rb +22 -22
- data/test/test_wizard.rb +50 -50
- metadata +26 -38
- data/.gemtest +0 -0
data/lib/quik/package.rb
CHANGED
@@ -1,115 +1,116 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Quik
|
4
|
-
|
5
|
-
class Package
|
6
|
-
|
7
|
-
def initialize( key ) ## e.g.
|
8
|
-
if key.index( '/' ).nil? ## if just 'gems' etc; assumbe
|
9
|
-
@key = "
|
10
|
-
else
|
11
|
-
@key = key # use as is e.g. seattlerb/hoe etc.
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
worker
|
67
|
-
|
68
|
-
###
|
69
|
-
###
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
#
|
77
|
-
# !/_layouts/
|
78
|
-
|
79
|
-
|
80
|
-
##
|
81
|
-
##
|
82
|
-
##
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
##
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Quik
|
4
|
+
|
5
|
+
class Package
|
6
|
+
|
7
|
+
def initialize( key ) ## e.g. quikstart/gems
|
8
|
+
if key.index( '/' ).nil? ## if just 'gems' etc; assumbe quikstart "standard" github org
|
9
|
+
@key = "quikstart/#{key}"
|
10
|
+
else
|
11
|
+
@key = key # use as is e.g. seattlerb/hoe etc.
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def remote_zip_url # remote zip url
|
17
|
+
"https://github.com/#{@key}/archive/master.zip"
|
18
|
+
end
|
19
|
+
|
20
|
+
def local_zip_name
|
21
|
+
## note: change / to --I-- for "flat" structure (e.g. no dirs)
|
22
|
+
@key.sub( '/', '--I--' ) # note: will NOT include/return .zip extension
|
23
|
+
end
|
24
|
+
|
25
|
+
def local_zip_dir
|
26
|
+
"." ## use ./tmp or ./dl or ~/.quik/cache - why?? why not??
|
27
|
+
end
|
28
|
+
|
29
|
+
def local_zip_path # local zip path
|
30
|
+
"#{local_zip_dir}/#{local_zip_name}.zip"
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
def download
|
36
|
+
src = remote_zip_url
|
37
|
+
dest_zip = local_zip_path
|
38
|
+
|
39
|
+
## make sure dest folder exists
|
40
|
+
FileUtils.mkdir_p( local_zip_dir ) unless Dir.exist?( local_zip_dir )
|
41
|
+
fetch_archive( src, dest_zip )
|
42
|
+
end
|
43
|
+
|
44
|
+
def unzip( unzip_dir )
|
45
|
+
src = local_zip_path
|
46
|
+
dest_unzip = unzip_dir ## local_unzip_dir
|
47
|
+
|
48
|
+
## check if folders exists? if not create folder in path
|
49
|
+
FileUtils.mkdir_p( dest_unzip ) unless Dir.exist?( dest_unzip )
|
50
|
+
unzip_archive( src, dest_unzip )
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def merge( root_dir, hash )
|
55
|
+
## replace/merge variable in files
|
56
|
+
Dir.chdir( "#{root_dir}" ) do
|
57
|
+
files = Dir[ '**/*' ] ## get all files
|
58
|
+
pp files
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
private
|
64
|
+
def fetch_archive( src, dest )
|
65
|
+
## step 1 - fetch archive
|
66
|
+
worker = Fetcher::Worker.new
|
67
|
+
worker.copy( src, dest )
|
68
|
+
### fix: add src.sha5
|
69
|
+
### inside folder
|
70
|
+
### lets us check if current HEAD version is in place across datafiles etc.
|
71
|
+
## - try HTTP HEAD ?? to check?
|
72
|
+
end
|
73
|
+
|
74
|
+
def unzip_archive( src, dest, opts={} )
|
75
|
+
### todo/fix: rename or remove root folder -- use opts { root: false or something??}
|
76
|
+
# e.g
|
77
|
+
# !/starter-gh-pages/_layouts/ becomes
|
78
|
+
# !/_layouts/ etc.
|
79
|
+
|
80
|
+
##
|
81
|
+
## note:
|
82
|
+
## skip all files in "root" folder
|
83
|
+
## only unzip files in /template(s)/ folder
|
84
|
+
|
85
|
+
Zip::File.open( src ) do |zipfile|
|
86
|
+
zipfile.each do |file|
|
87
|
+
if file.directory?
|
88
|
+
puts " skip directory zip entry - #{file.name}"
|
89
|
+
else
|
90
|
+
### fix: only cut-off if master or gh-pages ???
|
91
|
+
## check if others include root folder?
|
92
|
+
name = file.name[ file.name.index('/')+1..-1] ## cut-off root/first path entry
|
93
|
+
|
94
|
+
## note: name must start w/ template/ or templates/
|
95
|
+
## otherwise gets skipped as "top level" docu
|
96
|
+
if name =~ /^template(s)?\//
|
97
|
+
name = name[ name.index('/')+1..-1] ## cut-off first path entry (e.g. template(s)/)
|
98
|
+
|
99
|
+
path = File.join( dest, name)
|
100
|
+
puts " unzip file zip entry - #{file.name} to #{path}"
|
101
|
+
FileUtils.mkdir_p( File.dirname( path) )
|
102
|
+
## todo/fix: check - always overwrite if file exists - why? why not??
|
103
|
+
zipfile.extract(file, path) unless File.exist?(path)
|
104
|
+
else
|
105
|
+
puts " skip top-level docu file entry - #{file.name}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end # method unzip_theme
|
111
|
+
|
112
|
+
|
113
|
+
end # class Package
|
114
|
+
|
115
|
+
end # module Quik
|
116
|
+
|
data/lib/quik/version.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Quik
|
4
|
-
|
5
|
-
MAJOR =
|
6
|
-
MINOR =
|
7
|
-
PATCH = 0
|
8
|
-
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
9
|
-
|
10
|
-
def self.version
|
11
|
-
VERSION
|
12
|
-
end
|
13
|
-
|
14
|
-
# version string for generator meta tag (includes ruby version)
|
15
|
-
def self.banner
|
16
|
-
"quik/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.root
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
end # module Quik
|
24
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Quik
|
4
|
+
|
5
|
+
MAJOR = 1 ## todo: namespace inside version or something - why? why not??
|
6
|
+
MINOR = 0
|
7
|
+
PATCH = 0
|
8
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
9
|
+
|
10
|
+
def self.version
|
11
|
+
VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
# version string for generator meta tag (includes ruby version)
|
15
|
+
def self.banner
|
16
|
+
"quik/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.root
|
20
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
21
|
+
end
|
22
|
+
|
23
|
+
end # module Quik
|
24
|
+
|
data/lib/quik/wizard.rb
CHANGED
@@ -1,88 +1,88 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
## note:
|
5
|
-
## use global $QUIK_WIZARD_STDIN
|
6
|
-
## lets you redirect stdin for testing e.g $QUIK_WIZARD_STDIN = StringIO.new( 'test/n' )
|
7
|
-
$QUIK_WIZARD_IN = $stdin
|
8
|
-
|
9
|
-
|
10
|
-
module Quik
|
11
|
-
|
12
|
-
module Wizard ## use a different name e.g. WizardHelpers, FormHelpers, InputHelper, etc - why, why not??
|
13
|
-
|
14
|
-
def getstr ## use getstr to avoid conflict w/ gets (use better name? read_string, readline (already exists too), etc.?)
|
15
|
-
## note: gets will include trailing newline (user hits return to enter data)
|
16
|
-
## - use strip for now (remove leading and traling whitspaces) - might later just use chomp ? (jsut removes newlines)
|
17
|
-
$QUIK_WIZARD_IN.gets.strip
|
18
|
-
end
|
19
|
-
|
20
|
-
def say( text )
|
21
|
-
puts text
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
YES_REGEX = /y|yes|on|t|true/i ## support YAML true values - double check (YAML does NOT support t/f)
|
26
|
-
NO_REGEX = /n|no|off|f|false/i
|
27
|
-
|
28
|
-
def yes?( question ) ## defaults to yes - why, why not??
|
29
|
-
## todo: strip trailing question mark (?) if present (gets auto-included)
|
30
|
-
print( "Q: #{question} (y/n)? [y]: " )
|
31
|
-
str = getstr
|
32
|
-
if str.empty? || str =~ YES_REGEX
|
33
|
-
true
|
34
|
-
elsif str =~ NO_REGEX
|
35
|
-
false
|
36
|
-
else ## warn: unknown value??
|
37
|
-
true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def no?( question ) ## defaults to yes - why, why not??
|
42
|
-
## todo: strip trailing question mark (?) if present (gets auto-included)
|
43
|
-
print( "Q: #{question} (y/n)? [n]: " )
|
44
|
-
str = getstr
|
45
|
-
if str.empty? || str =~ NO_REGEX
|
46
|
-
true
|
47
|
-
elsif str =~ YES_REGEX
|
48
|
-
false
|
49
|
-
else ## warn: unknown value??
|
50
|
-
true
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def ask( question, default=nil )
|
56
|
-
## todo: strip trailing question mark (?) if present (gets auto-included)
|
57
|
-
if default
|
58
|
-
print( "Q: #{question}? [#{default}]: " )
|
59
|
-
else
|
60
|
-
print( "Q: #{question}?: " )
|
61
|
-
end
|
62
|
-
|
63
|
-
str = getstr
|
64
|
-
if default && str.empty? ## todo: best way to check for empty string?
|
65
|
-
str = default
|
66
|
-
end
|
67
|
-
str
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def select( title, options )
|
72
|
-
puts( "Q: #{title}: " )
|
73
|
-
options.each_with_index do |opt,i|
|
74
|
-
puts " #{i+1} - #{opt}"
|
75
|
-
end
|
76
|
-
print( " Your choice (1-#{options.size})? [1]: " )
|
77
|
-
str = getstr
|
78
|
-
if str.empty? ## todo: best way to check for empty string?
|
79
|
-
num = 0 ## default to first option for now
|
80
|
-
else
|
81
|
-
num = str.to_i ## note: defaults to 0 if cannot convert?
|
82
|
-
num -= 1 if num > 0 ## note: "convert" from 1-based to 0-based for ary; if invalid entry; default to 0
|
83
|
-
end
|
84
|
-
options[ num ]
|
85
|
-
end
|
86
|
-
|
87
|
-
end # module Wizard
|
88
|
-
end # module Quik
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
## note:
|
5
|
+
## use global $QUIK_WIZARD_STDIN
|
6
|
+
## lets you redirect stdin for testing e.g $QUIK_WIZARD_STDIN = StringIO.new( 'test/n' )
|
7
|
+
$QUIK_WIZARD_IN = $stdin
|
8
|
+
|
9
|
+
|
10
|
+
module Quik
|
11
|
+
|
12
|
+
module Wizard ## use a different name e.g. WizardHelpers, FormHelpers, InputHelper, etc - why, why not??
|
13
|
+
|
14
|
+
def getstr ## use getstr to avoid conflict w/ gets (use better name? read_string, readline (already exists too), etc.?)
|
15
|
+
## note: gets will include trailing newline (user hits return to enter data)
|
16
|
+
## - use strip for now (remove leading and traling whitspaces) - might later just use chomp ? (jsut removes newlines)
|
17
|
+
$QUIK_WIZARD_IN.gets.strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def say( text )
|
21
|
+
puts text
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
YES_REGEX = /y|yes|on|t|true/i ## support YAML true values - double check (YAML does NOT support t/f)
|
26
|
+
NO_REGEX = /n|no|off|f|false/i
|
27
|
+
|
28
|
+
def yes?( question ) ## defaults to yes - why, why not??
|
29
|
+
## todo: strip trailing question mark (?) if present (gets auto-included)
|
30
|
+
print( "Q: #{question} (y/n)? [y]: " )
|
31
|
+
str = getstr
|
32
|
+
if str.empty? || str =~ YES_REGEX
|
33
|
+
true
|
34
|
+
elsif str =~ NO_REGEX
|
35
|
+
false
|
36
|
+
else ## warn: unknown value??
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def no?( question ) ## defaults to yes - why, why not??
|
42
|
+
## todo: strip trailing question mark (?) if present (gets auto-included)
|
43
|
+
print( "Q: #{question} (y/n)? [n]: " )
|
44
|
+
str = getstr
|
45
|
+
if str.empty? || str =~ NO_REGEX
|
46
|
+
true
|
47
|
+
elsif str =~ YES_REGEX
|
48
|
+
false
|
49
|
+
else ## warn: unknown value??
|
50
|
+
true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def ask( question, default=nil )
|
56
|
+
## todo: strip trailing question mark (?) if present (gets auto-included)
|
57
|
+
if default
|
58
|
+
print( "Q: #{question}? [#{default}]: " )
|
59
|
+
else
|
60
|
+
print( "Q: #{question}?: " )
|
61
|
+
end
|
62
|
+
|
63
|
+
str = getstr
|
64
|
+
if default && str.empty? ## todo: best way to check for empty string?
|
65
|
+
str = default
|
66
|
+
end
|
67
|
+
str
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def select( title, options )
|
72
|
+
puts( "Q: #{title}: " )
|
73
|
+
options.each_with_index do |opt,i|
|
74
|
+
puts " #{i+1} - #{opt}"
|
75
|
+
end
|
76
|
+
print( " Your choice (1-#{options.size})? [1]: " )
|
77
|
+
str = getstr
|
78
|
+
if str.empty? ## todo: best way to check for empty string?
|
79
|
+
num = 0 ## default to first option for now
|
80
|
+
else
|
81
|
+
num = str.to_i ## note: defaults to 0 if cannot convert?
|
82
|
+
num -= 1 if num > 0 ## note: "convert" from 1-based to 0-based for ary; if invalid entry; default to 0
|
83
|
+
end
|
84
|
+
options[ num ]
|
85
|
+
end
|
86
|
+
|
87
|
+
end # module Wizard
|
88
|
+
end # module Quik
|