fanforce-cli 1.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2c93a7d41d24ba4fffa283343bf5b1cec0923efb
4
+ data.tar.gz: 6a267ce03515d30b0b2893adffc43a9df2bb24c6
5
+ SHA512:
6
+ metadata.gz: 173946476976342ebf6777d1095f1ac1fd7c8d3f32135865d0beefe106d058bb5a39341ae21855188a7623a2bf49d7403727837f49bb9c524ac173cadcd49eb3
7
+ data.tar.gz: 830fde0a3d785a7c4fcfc54911490d23551cc984eb3e0d1fbf06e011dd50aa6c23a9e8d87df15ca05c0770ac3ba9a3266a305c22c959d20271676be74627502e
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ .idea/
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ .DS_Store
data/.rbenv-gemsets ADDED
@@ -0,0 +1 @@
1
+ fanforce-cli
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,91 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fanforce-cli (1.0.0)
5
+ activesupport
6
+ bitbucket_rest_api
7
+ fanforce-api
8
+ heroku-api (= 0.3.8)
9
+ iron_worker_ng
10
+ multi_json
11
+ redis
12
+ rest-client
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ activesupport (4.1.4)
18
+ i18n (~> 0.6, >= 0.6.9)
19
+ json (~> 1.7, >= 1.7.7)
20
+ minitest (~> 5.1)
21
+ thread_safe (~> 0.1)
22
+ tzinfo (~> 1.1)
23
+ activesupport-inflector (0.1.0)
24
+ bitbucket_rest_api (0.1.5)
25
+ faraday (~> 0.8.1)
26
+ faraday_middleware (~> 0.9.0)
27
+ hashie (~> 2.0.5)
28
+ multi_json (~> 1.3)
29
+ nokogiri (>= 1.5.2)
30
+ simple_oauth
31
+ excon (0.16.10)
32
+ fanforce (0.19.0)
33
+ multi_json (>= 1.7.2)
34
+ rack
35
+ fanforce-api (0.23.0)
36
+ fanforce-exceptions (~> 0.5)
37
+ fanforce-validations (~> 0.7)
38
+ rest-client (~> 1.6.7)
39
+ fanforce-exceptions (0.5.1)
40
+ fanforce (~> 0.15)
41
+ fanforce-validations (0.7.1)
42
+ activesupport-inflector (~> 0.1)
43
+ fanforce (~> 0.15)
44
+ fanforce-exceptions (~> 0.5)
45
+ faraday (0.8.9)
46
+ multipart-post (~> 1.2.0)
47
+ faraday_middleware (0.9.1)
48
+ faraday (>= 0.7.4, < 0.10)
49
+ hashie (2.0.5)
50
+ heroku-api (0.3.8)
51
+ excon (~> 0.16.10)
52
+ i18n (0.6.11)
53
+ iron_core (1.0.5)
54
+ rest (>= 2.6.4)
55
+ iron_worker_ng (1.5.0)
56
+ bundler
57
+ iron_core (>= 1.0.0)
58
+ rubyzip (= 0.9.9)
59
+ json (1.8.1)
60
+ mime-types (1.25.1)
61
+ mini_portile (0.6.0)
62
+ minitest (5.4.0)
63
+ multi_json (1.10.1)
64
+ multipart-post (1.2.0)
65
+ net-http-persistent (2.9.4)
66
+ netrc (0.7.7)
67
+ nokogiri (1.6.3.1)
68
+ mini_portile (= 0.6.0)
69
+ rack (1.5.2)
70
+ rdoc (4.1.1)
71
+ json (~> 1.4)
72
+ redis (3.1.0)
73
+ rest (2.7.2)
74
+ net-http-persistent (>= 2.9.1)
75
+ rest_client (>= 1.7.1)
76
+ rest-client (1.6.8)
77
+ mime-types (~> 1.16)
78
+ rdoc (>= 2.4.2)
79
+ rest_client (1.7.3)
80
+ netrc (~> 0.7.7)
81
+ rubyzip (0.9.9)
82
+ simple_oauth (0.2.0)
83
+ thread_safe (0.3.4)
84
+ tzinfo (1.2.2)
85
+ thread_safe (~> 0.1)
86
+
87
+ PLATFORMS
88
+ ruby
89
+
90
+ DEPENDENCIES
91
+ fanforce-cli!
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Caleb Clark
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,144 @@
1
+ # fanforce-cli
2
+ The simplest way to create and manage a folder of Fanforce apps. This gem provides
3
+ bulk commands that you can run against your entire list.
4
+
5
+ ## Installation
6
+
7
+ Run this command from your command line:
8
+
9
+ gem install fanforce-cli
10
+
11
+ ## Usage
12
+
13
+ Run this command to view usage instructions
14
+
15
+ $ fanforce
16
+
17
+
18
+ ## Customizing Your Fanforce CLI Setup with .fanforce-cli
19
+ You can add a .fanforce-cli to any fanforce folder you've setup for your apps. It accepts any valid YAML markup.
20
+ Below is a example file that sets a custom local path for the fanforce-app-factory gem, plus a version:
21
+
22
+ ```yaml
23
+ app_factory_gem:
24
+ path: '../../fanforce-app-factory'
25
+ version: '~> 0.1.3'
26
+ ```
27
+ For more options see BitBucket and Heroku below.
28
+
29
+
30
+ ## Run Fanforce CLI Inside of an App
31
+
32
+ Sometimes you'll want to use cli commands inside a specific app. You can as long as the folder contains a config.ru
33
+ file, and the app is a subdirectory of a fanforce folder containing a .fanforce-cli file.
34
+
35
+
36
+ ## Supercharge Your Fanforce CLI
37
+
38
+ Fanforce-cli comes with a special application when you're running commands on a long list of apps and
39
+ each command is taking a long time to run. It forks each command and runs them in parallel. Only a subset of the full
40
+ cli commands are available with fanforce-supercharge. Run the following from your terminal to see your available
41
+ options:
42
+
43
+ ```
44
+ fanforce-supercharge
45
+ ```
46
+
47
+ ## BitBucket: Creating Repositories and Pushing
48
+ A BitBucket repository will be automatically setup for each new app if a bitbucket object is defined in your .fanforce-cli file:
49
+
50
+ ```yaml
51
+ bitbucket:
52
+ user: apps-by-me
53
+ password: password
54
+ ```
55
+
56
+ ## Heroku Apps: Creating and Updating
57
+ A heroku app will be automatically setup for each new app if a heroku object is defined in your .fanforce-cli file. You'll need
58
+ one for each environment (staging|production) you want apps setup for.
59
+
60
+ ```yaml
61
+ heroku:
62
+ production:
63
+ user: technical@fanforce.com
64
+ git_ssh_domain: heroku_fanforce
65
+ password: password
66
+ app_domain: ffapp.io
67
+ short_domain: fanforce.io
68
+ ```
69
+ The git_ssh_domain variable listed above is needed if you're pushing to multiple Heroku accounts as you'll need to specify
70
+ the SSH key that must be used (each Heroku account requires a unique ssh key). For example, the above git_ssh_domain variable
71
+ references the following lines in ~/.ssh/config:
72
+
73
+ ```
74
+ Host heroku_fanforce
75
+ HostName heroku.com
76
+ User technical@fanforce.com
77
+ IdentityFile ~/.ssh/heroku_fanforce
78
+ ```
79
+
80
+ See http://www.springloops.com/blog/git-config-for-mutiply-ssh-keys/ for more info.
81
+
82
+ ## Environment Variables
83
+ Fanforce CLI allows you to setup a list of env variables that can be loaded by your app it's running in your local
84
+ development environment, pushed to Heroku, or tasks setup on IronWorker.
85
+
86
+ First, you need to setup a folder called ".env" in your fanforce folder with a series of YAML files inside. The only required
87
+ file is _bind.yaml:
88
+
89
+ ```yaml
90
+ constantcontact:
91
+ - app-constantcontact
92
+ - plugin-constantcontact-subscribers
93
+
94
+ facebook:
95
+ - app-facebook
96
+ - plugin-facebook-friends
97
+ - plugin-facebook-posts
98
+
99
+ iron: ALL
100
+ ```
101
+
102
+ Each key is the filename (minus .yaml) of the YAML file holding a list of ENV variables. The array underneath is the folder names of apps
103
+ that these ENV variables will be loaded into. Alternatively, you can specify the keyword ALL if those ENV variables should
104
+ be loaded into all apps.
105
+
106
+ Second, you'll need to setup the filenames references in _bind.yaml. Each file contains a hash of ENV key/values organized
107
+ by RACK_ENV. Here's is an example of facebook.yaml (of course, you'll need to provide legit facebook api_keys and api_secrets):
108
+
109
+ ```yaml
110
+ development:
111
+ api_key: 175620799120142
112
+ api_secret: b4e86cbf9db2ch5777609396b1d0a52f
113
+
114
+ staging:
115
+ api_key: 362017347478160
116
+ api_secret: cf3605c0cnda02c95ddd1bb983a59e7a
117
+ ```
118
+
119
+ ## Using IronWorker
120
+
121
+ Fanforce CLI comes with built in support for using IronWorker in your apps:
122
+
123
+ ```
124
+ fanforce iron upload:development
125
+ ```
126
+
127
+ There are a couple things you'll want to setup first:
128
+
129
+ #### 1. Env Variables
130
+
131
+ - IRON_TOKEN
132
+ - IRON_PROJECT_ID
133
+
134
+ #### 2.
135
+
136
+
137
+
138
+ ## Contributing
139
+
140
+ 1. Fork it
141
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
142
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
143
+ 4. Push to the branch (`git push origin my-new-feature`)
144
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/fanforce ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fanforce/cli'
3
+
4
+ fanforce = Fanforce::CLI.new('fanforce')
5
+
6
+ if File.exists?("#{$HomeDir}/config.ru") and File.exists?("#{$HomeDir}/../.fanforce-cli")
7
+ ARGV.unshift(":#{File.basename($HomeDir)}")
8
+ $HomeDir = File.expand_path('..', $HomeDir)
9
+ fanforce.start(
10
+ :runtype => :single,
11
+ :allowed => [:update, :push, :restart, :bundle, :git, :iron, :version, :config, :cleanorgs, :upgrade],
12
+ )
13
+ elsif File.exists?("#{$HomeDir}/.fanforce-cli")
14
+ fanforce.start(
15
+ :runtype => :multiple,
16
+ :allowed => [:list, :create, :update, :delete, :push, :restart, :count, :bundle, :git, :iron, :version, :config, :cleanorgs, :upgrade],
17
+ )
18
+ else
19
+ puts 'NOT A VALID DIRECTORY'
20
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fanforce/cli'
3
+
4
+ Fanforce::CLI.new('fanforce-supercharge').start(
5
+ :runtype => :forked,
6
+ :allowed => [:update, :push, :restart, :bundle, :git, :iron, :version, :config, :cleanorgs],
7
+ )
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fanforce/cli/version'
5
+ require 'rubygems'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'fanforce-cli'
9
+ gem.version = Fanforce::CLI::VERSION
10
+ gem.authors = ['Caleb Clark']
11
+ gem.email = ['cclark@mobilizationlabs.com']
12
+ gem.description = %q{CLI for managing a folder of Fanforce apps}
13
+ gem.summary = %q{Manage a folder of Fanforce apps}
14
+ gem.homepage = ''
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = ['fanforce','fanforce-supercharge']
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.add_dependency 'redis'
22
+ gem.add_dependency 'rest-client'
23
+ gem.add_dependency 'iron_worker_ng'
24
+ gem.add_dependency 'activesupport'
25
+ gem.add_dependency 'heroku-api', '0.3.8'
26
+ gem.add_dependency 'multi_json'
27
+ gem.add_dependency 'bitbucket_rest_api'
28
+ gem.add_dependency 'fanforce'
29
+ gem.add_dependency 'fanforce-api'
30
+
31
+ end
@@ -0,0 +1,264 @@
1
+ require 'iron_worker_ng'
2
+ require 'fanforce/cli'
3
+
4
+ class Fanforce::CLI
5
+ require 'fanforce/cli/utils'
6
+ require 'fanforce/cli/files'
7
+ require 'fanforce/cli/app'
8
+ require 'fanforce/cli/apps'
9
+ require 'fanforce/cli/run'
10
+ require 'fanforce/cli/env'
11
+ require 'fanforce/cli/help'
12
+ require 'fanforce/cli/commands'
13
+ include Fanforce::CLI::Utils
14
+
15
+ def initialize(executable)
16
+ @executable = executable
17
+ $HomeDir = Shell.new.pwd
18
+ end
19
+
20
+ def start(options)
21
+ @runtype = options[:runtype]
22
+ @allowed_commands = options[:allowed]
23
+ setup_config
24
+ init_counter(Process.pid) if @runtype == :forked
25
+ parse_app_filter
26
+ parse_command
27
+ destroy_counter(Process.pid) if @runtype == :forked
28
+ end
29
+
30
+ def setup_config
31
+ puts 'ERROR: Fanforce CLI could not find the required config file.'.format(:red) if !File.exists?("#{$HomeDir}/.fanforce-cli")
32
+ $Config = format_config(YAML.load_file("#{$HomeDir}/.fanforce-cli"))
33
+ end
34
+
35
+ def parse_app_filter
36
+ if ARGV[0] =~ /^:((app)-(.+))$/
37
+ $Filter = {dir_name: $1}
38
+ ARGV.shift
39
+ end
40
+ end
41
+
42
+ #################################################################################
43
+
44
+ def parse_command
45
+
46
+ #################################################################
47
+
48
+ if ARGV.length == 0 or !@allowed_commands.include?(ARGV[0].to_sym)
49
+ puts Fanforce::CLI::Help.intro(@executable, @runtype)
50
+ puts Fanforce::CLI::Help.commands(@allowed_commands)
51
+
52
+ #################################################################
53
+
54
+ elsif ARGV[0] == 'list'
55
+ list_apps
56
+
57
+ #################################################################
58
+
59
+ elsif ARGV[0] == 'create'
60
+ ARGV[1] =~ /^app-([a-z0-9-]+)$/i || error('You supplied an invalid create command.', :create)
61
+ create_app($1)
62
+
63
+ #################################################################
64
+
65
+ elsif ARGV[0] == 'update'
66
+ ARGV[1] =~ /^(all|app-([a-z0-9-]+))$/ || error('You supplied an invalid update command.', :update) if ARGV[1]
67
+ ($2 && $2 != 'all') ? update_app($2) : run(:update)
68
+
69
+ #################################################################
70
+
71
+ elsif ARGV[0] == 'delete'
72
+ ARGV[1] =~ /^app-([a-z0-9-]+)$/ || error('You supplied an invalid delete command.', :delete)
73
+ confirm("Are you sure you want to delete all files, repositories, and other items for #{ARGV[1]}?")
74
+ delete_app($1)
75
+
76
+ #################################################################
77
+
78
+ elsif ARGV[0] == 'push'
79
+ ARGV[1] =~ /^(all|development|staging|production)$/ || error('You supplied an invalid push command.', :push)
80
+ environment = $1.to_sym
81
+ command = (ARGV[2] =~ /(:all|:heroku|:iron|bitbucket)$/) ? $1.to_sym : :all
82
+
83
+ confirm('Are you sure you want to push to all environments, including production?') if environment == :all
84
+ confirm('Are you sure you want to push to production?') if environment == :production
85
+ confirm("Are you sure you want to push to all services on #{environment}?") if command == :all
86
+
87
+ run(:push, environment, command)
88
+
89
+ #################################################################
90
+
91
+ elsif ARGV[0] == 'restart'
92
+ if ARGV[1].present?
93
+ ARGV[1] =~ /^(development|staging|production|all)?$/ || error('You supplied an invalid restart command.', :restart)
94
+ environment = $1.to_sym
95
+ else
96
+ environment = :development
97
+ end
98
+
99
+ confirm('Are you sure you want to restart all environments?') if environment == :all
100
+ run(:restart, environment)
101
+
102
+ #################################################################
103
+
104
+ elsif ARGV[0] == 'count'
105
+ count
106
+
107
+ #################################################################
108
+
109
+ elsif ARGV[0] == 'bundle'
110
+ ARGV[1] =~ /^(install|update)$/ || error('You supplied an invalid bundle command.', :bundle)
111
+
112
+ run(:bundle, $1.to_sym, ARGV[3..-1] || [])
113
+
114
+ #################################################################
115
+
116
+ elsif ARGV[0] == 'git' and ARGV[1] == 'status:overview'
117
+ run(:git_overview)
118
+
119
+ elsif ARGV[0] == 'git'
120
+ run(:git, ARGV[1..-1] || [])
121
+
122
+ #################################################################
123
+
124
+ elsif ARGV[0] == 'iron'
125
+ ARGV[1] =~ /^(upload|reset|delete)$/ || error('You supplied an invalid iron command.', :iron)
126
+ command = $1.to_sym
127
+
128
+ if ARGV[2].blank? or ARGV[2] =~ /^(all|development|staging|production)$/
129
+ environment = ($1.present?) ? $1.to_sym : :all
130
+ confirm("Are you sure you want to #{command} workers in all environments?") if environment == :all
131
+ else
132
+ error('You supplied an invalid iron environment.', :iron)
133
+ end
134
+
135
+ if command == :delete
136
+ delete_all_iron_workers(environment)
137
+ else
138
+ run(:iron, command, environment)
139
+ end
140
+
141
+ #################################################################
142
+
143
+ elsif ARGV[0] == 'cleanorgs'
144
+ ARGV[1] =~ /^(development|staging|production)$/ || error('You supplied an invalid cleanorgs command.', :cleanorgs)
145
+ environment = $1.to_sym
146
+
147
+ supercore_api_key = ARGV[2] || error('You supplied an invalid cleanorgs command.', :cleanorgs)
148
+
149
+ run(:cleanorgs, environment, supercore_api_key)
150
+
151
+ #################################################################
152
+
153
+ elsif ARGV[0] == 'version'
154
+ puts '---------------------------------------------------------------------------------------------------------------'
155
+ puts "You are using version #{Fanforce::CLI::VERSION} of Fanforce CLI"
156
+ puts '---------------------------------------------------------------------------------------------------------------'
157
+
158
+ elsif ARGV[0] == 'config'
159
+ puts '---------------------------------------------------------------------------------------------------------------'
160
+ if !File.exists?("#{$HomeDir}/.fanforce-cli")
161
+ puts 'Oops'.format(:red,:bold) + '... no ".fanforce-cli" file was found in this directory.'.format(:red)
162
+ else
163
+ puts $Config
164
+ end
165
+ puts '---------------------------------------------------------------------------------------------------------------'
166
+
167
+ elsif ARGV[0] == 'upgrade'
168
+ run(:upgrade)
169
+
170
+ end
171
+
172
+ end
173
+
174
+ #################################################################################
175
+
176
+ def run(method, *args)
177
+ (@runtype == :forked) ? run_forked(method, *args) : run_multiple(method, *args)
178
+ end
179
+
180
+ def run_multiple(method, *args)
181
+ if (dirs = Apps.dirs).size == 0
182
+ puts "\n---------------------------------------------------------------------------------------------------------------"
183
+ puts "#{'Oops'.format(:bold)}... no fanforce apps were found in this directory."
184
+ puts "---------------------------------------------------------------------------------------------------------------\n"
185
+ return
186
+ end
187
+
188
+ if self.respond_to?(:"preprocess_#{method}")
189
+ args << self.method(:"preprocess_#{method}").call
190
+ end
191
+ Apps.each do |app, processed_count, total_count|
192
+ self.method(:"run_#{method}").call(app.dir, processed_count, total_count, *args)
193
+ end
194
+ if self.respond_to?(:"postprocess_#{method}")
195
+ self.method(:"postprocess_#{method}").call
196
+ else
197
+ puts "\n---------------------------------------------------------------------------------------------------------------"
198
+ puts 'DONE!'
199
+ puts '---------------------------------------------------------------------------------------------------------------'
200
+ end
201
+ end
202
+
203
+ def run_forked(method, *args)
204
+ counter_id = Process.pid
205
+ processes = []
206
+ dirs = Apps.dirs
207
+ puts "\n---------------------------------------------------------------------------------------------------------------"
208
+ dirs.each_with_index do |app_dir, i|
209
+ puts "#{'Forking'.format(:white,:bold)} #{app_dir}"
210
+ end
211
+ dirs.each_with_index do |app_dir, i|
212
+ processes << fork do
213
+ response = capture_stdout do
214
+ self.method(:"run_#{method}").call(app_dir, 'PROCESSED_APPS_COUNT', dirs.size, *args)
215
+ end
216
+ puts response.gsub('PROCESSED_APPS_COUNT', incr_counter(counter_id).to_s)
217
+ end
218
+ sleep(0.25)
219
+ end
220
+
221
+ processes.each { |pid| Process.waitpid(pid) }
222
+ puts "\n---------------------------------------------------------------------------------------------------------------"
223
+ puts 'DONE!'
224
+ puts '---------------------------------------------------------------------------------------------------------------'
225
+ end
226
+
227
+ require 'stringio'
228
+ def capture_stdout
229
+ previous_stdout, previous_stderr = $stdout, $stderr
230
+ io = StringIO.new
231
+ $stdout = io
232
+ $stderr = io
233
+ IronCore::Logger.logger = ::Logger.new(io)
234
+ IronCore::Logger.logger.level = ::Logger::INFO
235
+ yield
236
+ io.string
237
+ ensure
238
+ $stdout = previous_stdout
239
+ $stderr = previous_stderr
240
+ end
241
+
242
+ def init_counter(counter_id)
243
+ File.open("#{$HomeDir}/.forked-counter-#{counter_id}", 'w') {|f| f.write('0') }
244
+ end
245
+
246
+ def incr_counter(counter_id)
247
+ new_count = nil
248
+ File.open("#{$HomeDir}/.forked-counter-#{counter_id}", File::RDWR|File::CREAT, 0644) do |f|
249
+ f.flock(File::LOCK_EX)
250
+ new_count = f.read.to_i + 1
251
+ f.rewind
252
+ f.write("#{new_count}\n")
253
+ f.flush
254
+ f.truncate(f.pos)
255
+ end
256
+ new_count
257
+ end
258
+
259
+ def destroy_counter(counter_id)
260
+ File.delete("#{$HomeDir}/.forked-counter-#{counter_id}")
261
+ end
262
+
263
+ end
264
+
@@ -0,0 +1,57 @@
1
+ class Fanforce::CLI::App
2
+ attr_reader :_id, :dir, :dir_name, :dir_root, :root_domain
3
+
4
+ def self.parse_dir_name(dir_name)
5
+ return if dir_name !~ /^(app-([a-z0-9-]+))\/?$/
6
+ {_id: $2, dir_name: $1}
7
+ end
8
+
9
+ def self.load(dir)
10
+ self.new(dir)
11
+ end
12
+
13
+ def initialize(dir)
14
+ raise "This is an invalid directory name for a fanforce addon: #{dir}" if dir !~ /^(.*)\/(app-([a-z0-9-]+))\/?$/
15
+ @_id = $3
16
+ @dir = "#{$1}/#{$2}"
17
+ @dir_root = $1
18
+ @dir_name = $2
19
+ @root_domain = Fanforce.apps_base_domain
20
+ end
21
+
22
+ def create_files(*filenames)
23
+ filenames.each do |filename|
24
+ Fanforce::CLI::Files.method(:"create_#{filename}").call(self)
25
+ end
26
+ end
27
+ alias create_file create_files
28
+
29
+ def update_files(*filenames)
30
+ filenames.each do |filename|
31
+ Fanforce::CLI::Files.method(:"update_#{filename}").call(self)
32
+ end
33
+ end
34
+ alias update_file update_files
35
+
36
+ def to_hash
37
+ {
38
+ _id: @_id,
39
+ dir_name: @dir_name,
40
+ dir_root: @dir_root,
41
+ dir: @dir,
42
+ }
43
+ end
44
+
45
+ def to_json
46
+ to_hash.to_json
47
+ end
48
+
49
+ def start_print
50
+ print "- #{@dir_name}... "
51
+ end
52
+
53
+ def end_print
54
+ puts 'DONE'
55
+ end
56
+
57
+ end