app_stack 0.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzBjNDgxMTQyZGE2NDMzNTRiYWExNTdlYmY4ZTNmZjVkMjNlMmZiMw==
5
+ data.tar.gz: !binary |-
6
+ OGIwNDZiNzNlNGQzYTViNDRmYTJhYWJmNzM5NGI1MzMxZmVkYWRkNA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MWU3MzhiNmQ5NDgzOTJiODM5YTQ0MmQ1YmMzMjNkNzI5ZmNjMDlmMjYwZDVm
10
+ OTY1MjA3OWE0MDcyYWQ3ZTc5NTU0NGE4OTY0MTY3MDk5YjEwMWU4MWI0Mjky
11
+ NmIzMGZkOTRiMGIzZjIzNGM4NjdlZGNmZTQwOGY0YmU0OWFkZmQ=
12
+ data.tar.gz: !binary |-
13
+ YzUzZGY3MjBkODAxZDFiNjM3NGY2MDhlNzY2NWUxMWI2ODk0ZGFkYjI4ZTNj
14
+ NjRmM2U5MjU1NmNjNDE3ZTE1ZGU3YjJjOWQyNWFlNDJmNzU0NjUxYjk2YTAz
15
+ YzFlYmRiMmYyOTg5OTlkMmYyYWI1NTVlNzM2YzMzZWZlYjBiNjY=
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ % AppStack: Merge Source Code from A Stack of App Modules
2
+ % Huang Wei <huangw@7lime.com>
3
+ % 3013-08-26
4
+
5
+ ## Concept
6
+
7
+ A configuration file `.app-stack.yml` in you app-root, in format like:
8
+
9
+ stack: [base-module auth-module ...]
10
+ app_dir: '../stack-apps'
11
+ tpl_ext: '.sample.erb'
12
+ verbose: 1
13
+ attrs:
14
+ dababase_name: 'nameofdatabase'
15
+ files:
16
+ README.md << __self
17
+ app/controllers/home_controller.rb << base-module
18
+
19
+ And in `Rakefile` add:
20
+
21
+ require 'app_stack'
22
+
23
+ namespace :stack do
24
+ task :update do
25
+ AppStack.new('.app-stack.yml').run!
26
+ end
27
+ end
28
+
29
+ Run `rack stack:up` will copy files according to the setting from yaml file,
30
+ and any new files that in you app stack but not in the current directory.
31
+
32
+ ## Template and Addition
33
+
34
+ If you have a file end with `.sample.erb`, for example `config.sample.erb`
35
+ in your stack besides `config`, this file will be used as a erb template, and
36
+ the output with combines with `attrs` set in your local yaml file. Those value
37
+ will inherited follow the stacks (from v0.0.2).
38
+
39
+ If you have a file name end with `.line_addon`, like `Gemfile.line_addon`,
40
+ the contents of this file will add to local `Gemefile` line by line unless
41
+ the line is already exists (from v0.0.3).
data/app_stack.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'app_stack/version'
3
+
4
+ Gem::Specification.new 'app_stack', AppStack::VERSION do |s|
5
+ s.description = 'Merge app source code in a stack to increase module reusability'
6
+ s.summary = 'Use as a rake task, define a stack of modules and app-stack will merge files from those stack-apps to the local application directory.'
7
+ s.authors = ['Huang Wei']
8
+ s.email = 'huangw@7lime.com'
9
+ s.homepage = 'https://github.com/7lime/app-stack-gem'
10
+ s.files = `git ls-files`.split("\n") - %w[.gitignore Rakefile]
11
+ s.license = 'MIT'
12
+ s.test_files = Dir.glob('{spec,test}/**/*.rb')
13
+
14
+ s.add_dependency 'tilt'
15
+ s.add_dependency 'term-ansicolor'
16
+ s.add_development_dependency 'rspec', '~> 2.5'
17
+ s.add_development_dependency 'simplecov', '~> 2.5'
18
+ end
19
+
@@ -0,0 +1,25 @@
1
+ ---
2
+ stack:
3
+ - base-app
4
+ - auth-app
5
+ stack_apps_dir: ../stack-apps
6
+ tpl_ext: .template.erb
7
+ addon_ext: .line_addon
8
+ verbose: 1
9
+ ignores:
10
+ - .+\.swap
11
+ - ~.+
12
+ - .+~
13
+ attrs:
14
+ application_name: My App
15
+ from_self: myapp
16
+ files:
17
+ README: __self
18
+ config: base-app
19
+ config/app.config.rb: base-app
20
+ config/configuration.yml: auth-app
21
+ config/configuration.yml.template.erb: auth-app
22
+ .app-stack.yml: __self
23
+ Gemfile: __self
24
+ Gemfile.line_addon: auth-app
25
+ Gemefile: auth-app
@@ -0,0 +1,5 @@
1
+ source 'http://ruby.taobao.org/'
2
+
3
+ gem 'fluentd'
4
+ gem 'cucumber'
5
+ gem 'devise'
@@ -0,0 +1 @@
1
+ readme in my app
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+
3
+ base_config = 'in base_app'
4
+ base_config = 'base_app' if base_config
@@ -0,0 +1,4 @@
1
+ Application:
2
+ Name: My App
3
+ Super: base
4
+ Inherit: myapp
File without changes
@@ -0,0 +1 @@
1
+ gem 'devise'
@@ -0,0 +1 @@
1
+ readme in auth_app
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+
3
+ auth_config = 'in auth_app'
4
+ auth_config = 'auth_app' if auth_config
@@ -0,0 +1,2 @@
1
+ This:
2
+ File: Not Set
@@ -0,0 +1,4 @@
1
+ Application:
2
+ Name: <%= application_name %>
3
+ Super: <%= from_super %>
4
+ Inherit: <%= from_self %>
@@ -0,0 +1,23 @@
1
+ ---
2
+ stack:
3
+ - base-app
4
+ - auth-app
5
+ stack_apps_dir: ../stack-apps
6
+ tpl_ext: .template.erb
7
+ verbose: 1
8
+ ignores:
9
+ - .+\.swap
10
+ - ~.+
11
+ - .+~
12
+ attrs:
13
+ application_name: My App
14
+ from_super: 'base'
15
+ from_self: 'base'
16
+ files:
17
+ .app-stack.yml: __self
18
+ README: __self
19
+ config: base-app
20
+ config/app.config.rb: base-app
21
+ config/.app.config.rb.swp: auth-app
22
+ config/configuration.yml: auth-app
23
+ config/configuration.yml.template.erb: auth-app
@@ -0,0 +1 @@
1
+ readme in base_app
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+
3
+ base_config = 'in base_app'
4
+ base_config = 'base_app' if base_config
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ # AppStack module
4
+ module AppStack
5
+ VERSION = '0.0.3'
6
+ end
data/lib/app_stack.rb ADDED
@@ -0,0 +1,150 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+ require 'find'
5
+ require 'fileutils'
6
+ require 'term/ansicolor'
7
+ # mixin String class for term-color methods
8
+ class String; include Term::ANSIColor end
9
+ require 'tilt/erb'
10
+ require 'ostruct'
11
+
12
+ ## A namespace for app-stack based modules
13
+ module AppStack
14
+
15
+ CONF_FILE = '.app-stack.yml'
16
+
17
+ def run!(file = '.app-stack.yml')
18
+ # load configuration
19
+ @config = YAML.load(File.read(file))
20
+ @attr = {}
21
+ # assign default values:
22
+ @app_root = File.expand_path(File.dirname(file)) unless @config['app_root']
23
+ @stack_apps_dir = @config['stack_apps_dir']
24
+ @stack_apps_dir = @app_root + '/' +
25
+ @stack_apps_dir if @stack_apps_dir.match(/^\.\.?\//)
26
+
27
+ @files = @config['files'] || {}
28
+ register_own_files!
29
+ # loop over each stack application
30
+ @config['stack'].each { |stack_app| do_copy(stack_app) }
31
+ # rewrite configuration back to app-stack file
32
+ @config['files'] = @files
33
+ File.open(file, 'wb') { |fh| fh.puts YAML.dump(@config) }
34
+ end
35
+
36
+ def newer(f1, f2)
37
+ return false unless File.exists?(f1)
38
+ return true unless File.exists?(f2)
39
+ File.mtime(f1) > File.mtime(f2)
40
+ end
41
+
42
+ def do_addon!(f, basename)
43
+ target = File.expand_path(@app_root + '/' + basename)
44
+ # add on always applies
45
+ addon_file = f + @config['addon_ext']
46
+ if File.exists?(addon_file) # && newer(addon_file, target)
47
+ add_lines = File.read(addon_file).split("\n")
48
+ add_lines -= File.read(target).split("\n")
49
+ afh = File.open(target, 'a')
50
+ add_lines.each { |line| afh.puts line }
51
+ afh.close
52
+ done = 'add lines'.bold.green if add_lines.size > 0
53
+ end
54
+ end
55
+
56
+ # rubocop:disable MethodLength
57
+ def copy_file!(f, basename)
58
+ return 'ignored'.white if ignores(basename)
59
+
60
+ done = 'keeped'.green
61
+ target = File.expand_path(@app_root + '/' + basename)
62
+ # directory?
63
+ if File.directory?(f)
64
+ if File.directory?(target)
65
+ done = 'exists'.green
66
+ else
67
+ FileUtils.mkdir_p target
68
+ done = 'created'.bold.green
69
+ end
70
+ else
71
+ tpl_file = f + @config['tpl_ext']
72
+ if File.exists?(tpl_file) && newer(tpl_file, target)
73
+ @tilt = Tilt::ERBTemplate.new(tpl_file)
74
+ oh = File.open(target, 'wb')
75
+ oh.write @tilt.render(OpenStruct.new(@attr.merge(@config['attrs'])))
76
+ oh.close
77
+ done = 'rendered'.bold.green
78
+ elsif newer(f, target)
79
+ FileUtils.copy f, target
80
+ done = 'copied'.bold.green
81
+ end
82
+ end
83
+ done
84
+ end
85
+ # rubocop:able MethodLength
86
+
87
+ def ignores(f)
88
+ @config['ignores'] = [] unless @config['ignores']
89
+ return true if f == CONF_FILE
90
+ return true if /#{@config['tpl_ext']}$/.match(f)
91
+ return true if /#{@config['addon_ext']}$/.match(f)
92
+ @config['ignores'].each do |ptn|
93
+ return true if /#{ptn}/.match(f)
94
+ end
95
+ false
96
+ end
97
+
98
+ def do_copy(stack_app)
99
+ raise 'invalid app name "__self"' if stack_app == '__self'
100
+ stack_app_dir = File.expand_path(@stack_apps_dir + '/' + stack_app)
101
+
102
+ # merge attr setting
103
+ if File.exists?(stack_app_dir + '/' + CONF_FILE)
104
+ stack_conf = YAML.load(File.read(stack_app_dir + '/' + CONF_FILE))
105
+ @attr.merge! stack_conf['attrs'] if stack_conf['attrs'] &&
106
+ stack_conf['attrs'].is_a?(Hash)
107
+ end
108
+
109
+ Find.find(stack_app_dir).each do |f|
110
+ basename = f.sub(/^#{stack_app_dir}\//, '')
111
+ next if f == stack_app_dir
112
+ do_copy_it = @files[basename] ? false : true
113
+ do_copy_it = true if @files[basename] == stack_app
114
+ if do_copy_it
115
+ @files[basename] = stack_app unless @files[basename]
116
+ done = copy_file!(f, basename)
117
+ carp "From #{stack_app.blue.bold} #{basename.bold}", done
118
+ else
119
+ carp "From #{stack_app.blue.bold} #{basename.bold}",
120
+ 'skip, use '.white + @files[basename]
121
+ end
122
+ done = do_addon!(f, basename)
123
+ carp "From #{stack_app.blue.bold} addon #{basename.bold}", done if done
124
+ end
125
+ end
126
+
127
+ # for files already in the app root, register to no-copy list
128
+ def register_own_files!
129
+ Find.find(@app_root).each do |f|
130
+ next if f == @app_root
131
+ basename = f.sub(/^#{@app_root}\//, '')
132
+ unless @files[basename]
133
+ carp "From #{'self'.blue.bold} #{basename.bold}", 'registed'.green.bold
134
+ @files[basename] = '__self'
135
+ end
136
+
137
+ carp "From #{'self'.blue.bold} #{basename.bold} ",
138
+ 'keep'.green if @files[basename] == '__self'
139
+ end
140
+ end
141
+
142
+ def carp(job, state = 'done'.green)
143
+ return unless @config['verbose'] && @config['verbose'] > 0
144
+ dots = 70 - job.size
145
+ dots = 0 if dots < 0
146
+ puts job + ' ' + '.' * dots + ' ' + state
147
+ end
148
+
149
+ extend self
150
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: app_stack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Huang Wei
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tilt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: term-ansicolor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.5'
69
+ description: Merge app source code in a stack to increase module reusability
70
+ email: huangw@7lime.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - app_stack.gemspec
77
+ - examples/my_app/.app-stack.yml
78
+ - examples/my_app/Gemfile
79
+ - examples/my_app/README
80
+ - examples/my_app/config/app.config.rb
81
+ - examples/my_app/config/configuration.yml
82
+ - examples/stack-apps/auth-app/Gemfile
83
+ - examples/stack-apps/auth-app/Gemfile.line_addon
84
+ - examples/stack-apps/auth-app/README
85
+ - examples/stack-apps/auth-app/config/app.config.rb
86
+ - examples/stack-apps/auth-app/config/configuration.yml
87
+ - examples/stack-apps/auth-app/config/configuration.yml.template.erb
88
+ - examples/stack-apps/base-app/.app-stack.yml
89
+ - examples/stack-apps/base-app/README
90
+ - examples/stack-apps/base-app/config/app.config.rb
91
+ - lib/app_stack.rb
92
+ - lib/app_stack/version.rb
93
+ homepage: https://github.com/7lime/app-stack-gem
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.0.6
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Use as a rake task, define a stack of modules and app-stack will merge files
117
+ from those stack-apps to the local application directory.
118
+ test_files: []