azdeploy 1.0.30 → 1.0.31

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cfe21fedf88697a8d17753b2367be79579268ee
4
- data.tar.gz: f0f40c6f91d5c357dd11882fe9deb0cc51a65644
3
+ metadata.gz: 674516fefe82d0733e648702a2ec69fa968a7b8e
4
+ data.tar.gz: 30a2c43e9661a78c24ab4162ce1594ed05e50d4e
5
5
  SHA512:
6
- metadata.gz: 082eb1b7b1dea05ffa673c76fa0598fd32d2dbf8ffce50907a2e3dd00549dc26192349d515f7073ddbb4ae8bb21f907141fe33b7fb66999c0da20f51a5d26806
7
- data.tar.gz: 8a77396d729b53ce2bacd24b0aa083afad51b48d2b6cabaf8a9f692de8230f6057d3794df0f965d45133c1acb5f6b95935612fb5b963f2299383521b2409b540
6
+ metadata.gz: e78e962ec74558b18003e56e1f10db172fc88b25e06f77214126d9765c698f02e3372142285f31bbf291ae836e7b669998ef00db75529fa6f993989c0367af4e
7
+ data.tar.gz: 1fc74904ea5c665d5925916554803ad89e4035685a4c486625f1081e07988d21be4a33b8296104de957f9e81589fc2210b3878037abb099bfd398193539c9a9b
data/azdeploy.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'azdeploy'
3
- s.version = '1.0.30'
4
- s.date = '2015-10-04'
3
+ s.version = '1.0.31'
4
+ s.date = '2015-12-16'
5
5
  s.summary = 'Setup and scripting support for .Net project builds'
6
6
  s.description = 'Azure Deployment Gem. Provides easy setup and deployment scripting support for .Net project builds'
7
7
  s.authors = ['Suresh Batta']
data/lib/azdeploy.rb CHANGED
@@ -2,14 +2,15 @@ require_relative 'install.rb'
2
2
  require_relative 'transform.rb'
3
3
  require_relative 'build.rb'
4
4
  require_relative 'dependency.rb'
5
+ require_relative 'semantic_versioning.rb'
5
6
 
6
7
  # installation
7
8
  installers = [
8
- 'ruby', 'devkit', 'doxygen', 'gems'
9
+ 'ruby', 'devkit', 'doxygen', 'gems'
9
10
  ]
10
11
 
11
- installers.each { |method|
12
- exit if !send("check_#{method}")
12
+ installers.each { |method|
13
+ exit if !send("check_#{method}")
13
14
  }
14
15
 
15
16
  require 'rubygems'
@@ -19,4 +20,5 @@ require 'azure'
19
20
  # includes for rake build
20
21
  include FileTest
21
22
  require 'albacore'
22
- require 'semver'
23
+ require 'semver'
24
+ require 'net/http'
data/lib/install.rb CHANGED
@@ -1,171 +1,170 @@
1
- require 'net/http'
2
1
 
3
2
  def download_file(sourcePath, filePath, localFileLocation)
4
- Net::HTTP.start(sourcePath) do |http|
5
- resp = http.get(filePath)
6
- f = open(localFileLocation, 'wb')
7
- begin
8
- requestPath = "http://#{sourcePath}#{filePath}"
9
- puts "Downloading #{requestPath}..."
10
- http.request_get(requestPath) do |resp|
11
- resp.read_body do |segment|
12
- f.write(segment)
13
- end
14
- end
15
- rescue
16
- puts $!
17
- return false
18
- ensure
19
- f.close()
20
- end
21
- end
22
- return true
3
+ Net::HTTP.start(sourcePath) do |http|
4
+ resp = http.get(filePath)
5
+ f = open(localFileLocation, 'wb')
6
+ begin
7
+ requestPath = "http://#{sourcePath}#{filePath}"
8
+ puts "Downloading #{requestPath}..."
9
+ http.request_get(requestPath) do |resp|
10
+ resp.read_body do |segment|
11
+ f.write(segment)
12
+ end
13
+ end
14
+ rescue
15
+ puts $!
16
+ return false
17
+ ensure
18
+ f.close()
19
+ end
20
+ end
21
+ return true
23
22
  end
24
23
 
25
24
  def install_file(cmd, versionedExeFile)
26
- begin
27
- installerOutput = `#{cmd}`
28
- puts installerOutput
29
- rescue
30
- puts $!
31
- return false
32
- ensure
33
- puts 'Cleaning up...'
34
- cmd = "#{versionedExeFile}"
35
- installerOutput = `del #{cmd}`
36
- puts installerOutput
37
- end
38
- return true
25
+ begin
26
+ installerOutput = `#{cmd}`
27
+ puts installerOutput
28
+ rescue
29
+ puts $!
30
+ return false
31
+ ensure
32
+ puts 'Cleaning up...'
33
+ cmd = "#{versionedExeFile}"
34
+ installerOutput = `del #{cmd}`
35
+ puts installerOutput
36
+ end
37
+ return true
39
38
  end
40
39
 
41
40
  def gem_exists(name, version)
42
- begin
43
- gem name, version
44
- rescue Gem::LoadError
45
- puts "failed to load gem #{name} -v #{version}"
46
- Gem.clear_paths
47
- return false
48
- end
49
- return true
41
+ begin
42
+ gem name, version
43
+ rescue Gem::LoadError
44
+ puts "failed to load gem #{name} -v #{version}"
45
+ Gem.clear_paths
46
+ return false
47
+ end
48
+ return true
50
49
  end
51
50
 
52
51
  $version_map = {
53
- '1.9.3-p551' => {
54
- :devkit => 'DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe',
55
- :gems => {
56
- 'albacore' => '0.3.5',
57
- 'semver2' => '3.3.3',
58
- 'nokogiri' => '1.6.4.1',
59
- 'zip' => '2.0.2',
60
- 'azure' => '0.6.4'
61
- },
62
- },
63
- '2.0.0-p481' => {
64
- :devkit => 'DevKit-mingw64-32-4.7.2-20130224-1151-sfx.exe',
65
- :gems => {
66
- 'albacore' => '0.3.6',
67
- 'semver2' => '3.3.3',
68
- 'nokogiri' => '1.6.4.1',
69
- 'azure' => '0.6.4'
70
- }
71
- }
52
+ '1.9.3-p551' => {
53
+ :devkit => 'DevKit-tdm-32-4.5.2-20111229-1559-sfx.exe',
54
+ :gems => {
55
+ 'albacore' => '0.3.5',
56
+ 'semver2' => '3.3.3',
57
+ 'nokogiri' => '1.6.4.1',
58
+ 'zip' => '2.0.2',
59
+ 'azure' => '0.6.4'
60
+ },
61
+ },
62
+ '2.0.0-p481' => {
63
+ :devkit => 'DevKit-mingw64-32-4.7.2-20130224-1151-sfx.exe',
64
+ :gems => {
65
+ 'albacore' => '0.3.6',
66
+ 'semver2' => '3.3.3',
67
+ 'nokogiri' => '1.6.4.1',
68
+ 'azure' => '0.6.4'
69
+ }
70
+ }
72
71
  }
73
72
  $selected_version = {}
74
73
 
75
74
  # Ruby version check
76
75
  def check_ruby
77
- puts 'Checking ruby version...'
78
- # check if expected ruby version exists. If not download and install ruby
79
- rubyVersion = "#{RUBY_VERSION}"
80
- localVersion = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
81
- expectedVersion1 = '1.9.3-p551'
82
- expectedVersion2 = '2.0.0-p481'
83
- if (!rubyVersion.nil? && (localVersion != expectedVersion1 && localVersion != expectedVersion2))
84
- puts "Uninstall incompatible version of ruby: #{localVersion} and install version: #{expectedVersion1} or #{expectedVersion2}. Then Restart rake. Goto http://rubyinstaller.org/downloads/"
85
- return false
86
- end
87
-
88
- $selected_version = $version_map[localVersion]
89
- puts 'Ruby ok'
90
-
91
- return true
76
+ puts 'Checking ruby version...'
77
+ # check if expected ruby version exists. If not download and install ruby
78
+ rubyVersion = "#{RUBY_VERSION}"
79
+ localVersion = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
80
+ expectedVersion1 = '1.9.3-p551'
81
+ expectedVersion2 = '2.0.0-p481'
82
+ if (!rubyVersion.nil? && (localVersion != expectedVersion1 && localVersion != expectedVersion2))
83
+ puts "Uninstall incompatible version of ruby: #{localVersion} and install version: #{expectedVersion1} or #{expectedVersion2}. Then Restart rake. Goto http://rubyinstaller.org/downloads/"
84
+ return false
85
+ end
86
+
87
+ $selected_version = $version_map[localVersion]
88
+ puts 'Ruby ok'
89
+
90
+ return true
92
91
  end
93
92
 
94
93
  ### devkit version check
95
94
  def check_devkit
96
- # check if devkit exists
97
- puts 'Checking devkit version...'
98
- rubyPath = `where.exe ruby.exe`
99
- rubyPath['bin\ruby.exe'] = 'devkit'
100
- rubyPath = rubyPath.sub("\n", '') #doublequotes required for Line break, gotcha
101
- if (!File.directory?(rubyPath))
102
- puts 'devkit not found'
103
- # if not download, install and setup devkit
104
- puts 'Downloading devkit...'
105
-
106
- sourcePath = 'cdn.rubyinstaller.org'
107
- versionedExeFile = $selected_version[:devkit]
108
- filePath = "/archives/devkits/#{versionedExeFile}?direct"
109
- return false if !download_file(sourcePath, filePath, versionedExeFile)
110
-
111
- puts 'Devkit installation in progress...'
112
- cmd = "#{versionedExeFile} -y -o\"#{rubyPath}\"" #no space after -o, gotcha
113
- puts cmd
114
- return false if !install_file(cmd, versionedExeFile)
115
-
116
- puts 'Setting up devkit...'
117
- Dir.chdir "#{rubyPath}"
118
- cmd = 'ruby dk.rb init'
119
- cmdoutput = `#{cmd}`
120
- puts cmdoutput
121
- if !cmdoutput.to_s.include?('Initialization complete!')
122
- puts 'Error: could not initialize devkit.'
123
- return false
124
- end
125
-
126
- cmd = 'ruby dk.rb review'
127
- cmdoutput = `#{cmd}`
128
- puts cmdoutput
129
- if !cmdoutput.to_s.include?('DevKit functionality will be injected')
130
- puts 'Error: devkit review failed'
131
- return false
132
- end
133
-
134
- cmd = 'ruby dk.rb install'
135
- cmdoutput = `#{cmd}`
136
- puts cmdoutput
137
- puts 'Restart console since environment variables are now updated'
138
-
139
- return false
140
- end
141
-
142
- puts 'devkit ok'
143
- return true
95
+ # check if devkit exists
96
+ puts 'Checking devkit version...'
97
+ rubyPath = `where.exe ruby.exe`
98
+ rubyPath['bin\ruby.exe'] = 'devkit'
99
+ rubyPath = rubyPath.sub("\n", '') #doublequotes required for Line break, gotcha
100
+ if (!File.directory?(rubyPath))
101
+ puts 'devkit not found'
102
+ # if not download, install and setup devkit
103
+ puts 'Downloading devkit...'
104
+
105
+ sourcePath = 'cdn.rubyinstaller.org'
106
+ versionedExeFile = $selected_version[:devkit]
107
+ filePath = "/archives/devkits/#{versionedExeFile}?direct"
108
+ return false if !download_file(sourcePath, filePath, versionedExeFile)
109
+
110
+ puts 'Devkit installation in progress...'
111
+ cmd = "#{versionedExeFile} -y -o\"#{rubyPath}\"" #no space after -o, gotcha
112
+ puts cmd
113
+ return false if !install_file(cmd, versionedExeFile)
114
+
115
+ puts 'Setting up devkit...'
116
+ Dir.chdir "#{rubyPath}"
117
+ cmd = 'ruby dk.rb init'
118
+ cmdoutput = `#{cmd}`
119
+ puts cmdoutput
120
+ if !cmdoutput.to_s.include?('Initialization complete!')
121
+ puts 'Error: could not initialize devkit.'
122
+ return false
123
+ end
124
+
125
+ cmd = 'ruby dk.rb review'
126
+ cmdoutput = `#{cmd}`
127
+ puts cmdoutput
128
+ if !cmdoutput.to_s.include?('DevKit functionality will be injected')
129
+ puts 'Error: devkit review failed'
130
+ return false
131
+ end
132
+
133
+ cmd = 'ruby dk.rb install'
134
+ cmdoutput = `#{cmd}`
135
+ puts cmdoutput
136
+ puts 'Restart console since environment variables are now updated'
137
+
138
+ return false
139
+ end
140
+
141
+ puts 'devkit ok'
142
+ return true
144
143
  end
145
144
 
146
145
  # doxygen check
147
146
  def check_doxygen
148
- # download doxygen
149
- return true
147
+ # download doxygen
148
+ return true
150
149
  end
151
150
 
152
151
  # check and install required gems
153
152
  def check_gems
154
- puts 'Checking required gems...'
155
- $selected_version[:gems].each {|key, value|
156
- if !gem_exists(key, "=#{value}")
157
- begin
158
- puts "Installing missing gem: #{key}"
159
- cmd = "gem install #{key} -v #{value}"
160
- cmdoutput = `#{cmd}`
161
- puts cmdoutput
162
- rescue
163
- puts 'gem install failed'
164
- puts $!
165
- return false # don't continue if even one gem install fails
166
- end
167
- end
168
- }
169
- # all gems installed
170
- return true
171
- end
153
+ puts 'Checking required gems...'
154
+ $selected_version[:gems].each {|key, value|
155
+ if !gem_exists(key, "=#{value}")
156
+ begin
157
+ puts "Installing missing gem: #{key}"
158
+ cmd = "gem install #{key} -v #{value}"
159
+ cmdoutput = `#{cmd}`
160
+ puts cmdoutput
161
+ rescue
162
+ puts 'gem install failed'
163
+ puts $!
164
+ return false # don't continue if even one gem install fails
165
+ end
166
+ end
167
+ }
168
+ # all gems installed
169
+ return true
170
+ end
@@ -0,0 +1,280 @@
1
+ class SemverVersioning
2
+
3
+ # url template of file to check for version info with repo, branch and file path to replace
4
+ URLTEMPLATE ||= "%s/raw/%s/%s"
5
+
6
+ def open url
7
+ Net::HTTP.get(URI.parse url)
8
+ end
9
+
10
+ def display_local_changes_to_user
11
+ git_status = `git status -s`
12
+ if (git_status != nil || git_status != GlobalConstants::EMPTY)
13
+ puts '********** Local semver/s updated. Please commit the change.'
14
+ end
15
+ end
16
+
17
+ def fetch_updated_semver
18
+
19
+ updated_semver = get_update_semver_file_with_versions
20
+
21
+ #for local run user did not increment any semver
22
+ if updated_semver[3] == 0
23
+ puts '*********** No semver incremented detected. ***********'
24
+ return nil
25
+ end
26
+
27
+ version_remote = updated_semver[1].split('.')
28
+ version_local = updated_semver[2].split('.')
29
+
30
+ incremented = is_semver_incremented version_remote, version_local
31
+
32
+ [updated_semver[0].gsub("#{VERSIONING}/", ''), incremented]
33
+ end
34
+
35
+ def get_update_semver_file_with_versions
36
+ count = 0
37
+ semver_file = ''
38
+ version_remote = ''
39
+ version_local = ''
40
+
41
+ semvers = get_file_list VERSIONING, 'semver'
42
+ if(semvers.empty?)
43
+ raise "************Error - no semver files found at #{VERSIONING}********"
44
+ end
45
+
46
+ semvers.each { |semver|
47
+ v1 = get_repo_version semver
48
+ v2 = get_current_version VERSIONING, semver.gsub("#{VERSIONING}/", '')
49
+ if (!same_versions(v1, v2))
50
+ puts "#{semver} version changed"
51
+ semver_file = semver
52
+ version_remote = v1
53
+ version_local = v2
54
+ count = count + 1
55
+ end
56
+ }
57
+ if count > 1
58
+ raise '*********** Error - Version increment is expected in a single semver file and can be only one of major|minor|patch ************'
59
+ return
60
+ end
61
+
62
+ [semver_file, version_remote, version_local, count]
63
+ end
64
+
65
+ def is_semver_incremented version_remote, version_local
66
+ is_incremented = [version_local[0].to_i - version_remote[0].to_i > 0, version_local[1].to_i - version_remote[1].to_i > 0, version_local[2].to_i - version_remote[2].to_i > 0]
67
+
68
+ if is_incremented[0]
69
+ if (version_local[1] != 0 || version_local[2] != 0)
70
+ raise 'Error - major version is incremented. Minor and Patch should be 0. Cannot continue build. Exiting....'
71
+ end
72
+ end
73
+
74
+ if is_incremented[1]
75
+ if is_incremented[0]
76
+ raise 'Error - cannot increment both major and minor version. . Exiting....'
77
+ end
78
+ end
79
+
80
+ if is_incremented[2]
81
+ if(is_incremented[0] || is_incremented[1])
82
+ raise 'Error - cannot increment major, minor and patch together. . Exiting....'
83
+ end
84
+ end
85
+
86
+ if is_incremented[0]
87
+ 'major'
88
+ elsif is_incremented[1]
89
+ 'minor'
90
+ elsif is_incremented[2]
91
+ 'patch'
92
+ end
93
+ end
94
+
95
+ def get_branch_name
96
+ current_branch = ENV['GIT_BRANCH_NAME']
97
+ if current_branch.nil?
98
+ raise '********GIT_BRANCH_NAME environment variable required for local rake run. Cannot continue with build. Exiting..............********'
99
+ else
100
+ current_branch
101
+ end
102
+ end
103
+
104
+ def get_remote_name
105
+ remote_name = ENV['GIT_REMOTE_NAME']
106
+ if remote_name.nil?
107
+ raise '********GIT_REMOTE_NAME environment variable required for local rake run. Cannot continue with build. Exiting..............********'
108
+ else
109
+ @remote = `git remote -v`.split("\n")
110
+ @remote.each { |val|
111
+ if val =~ /#{remote_name}/
112
+ return val.split(" ")[1].sub('.git', '')
113
+ end
114
+ }
115
+ end
116
+ end
117
+
118
+ def get_repo_version semver
119
+ remote_name = get_remote_name
120
+ branch_name = get_branch_name
121
+ url = URLTEMPLATE % [remote_name, branch_name, semver]
122
+ page_content = open(url)
123
+ repo_version = get_semver_version(page_content)
124
+ repo_version
125
+ end
126
+
127
+ def get_current_version path, semver
128
+ location = File.join path, semver
129
+ content = File.read(location)
130
+ current_version = get_semver_version(content)
131
+ current_version
132
+ end
133
+
134
+ def get_semver_version(content)
135
+ s = content.split("\n")
136
+ val = ''
137
+ s.each{ |i|
138
+ if (i.start_with?(':'))
139
+ x = i.split(': ')[1].strip
140
+ x.gsub!("'", '')
141
+ if (x.length != 0)
142
+ val = val + x.to_s + '.'
143
+ end
144
+ end
145
+ }
146
+ val.chomp('.')
147
+ end
148
+
149
+ def same_versions version1, version2
150
+ version1 == version2
151
+ end
152
+
153
+ # Method to be used from the upgrade project, to update single or multiple semvers on team city
154
+ def auto_update_semver project_name, semver_location, semver_file, semver_dimension
155
+ Dir.chdir project_name if File.basename(Dir.pwd) != project_name
156
+ if(semver_file.nil? || semver_file.strip == '' || semver_file == '.semver')
157
+ increment_version '.semver', semver_dimension
158
+ else
159
+ increment_version File.join(semver_location, semver_file), semver_dimension
160
+ update_dependent_semvers project_name, semver_location, semver_file, semver_dimension
161
+ end
162
+ end
163
+
164
+ # Method invoked to update multiple semvers locally. This will not update single semver. That has to be done manually
165
+ def auto_update_local_semver
166
+ if(!Dir.exist?(VERSIONING) || File.exist?('.semver'))
167
+ raise 'Error - local upgrade process only applies to projects with multiple semvers. If you have one semver at root level, please update it manually if needed. Do not invoke auto_update_local_semver task.'
168
+ end
169
+ updated_semver_with_version_state = fetch_updated_semver
170
+ if updated_semver_with_version_state != nil
171
+ update_dependent_semvers PRODUCT, VERSIONING, updated_semver_with_version_state[0], updated_semver_with_version_state[1]
172
+ end
173
+
174
+ display_local_changes_to_user
175
+ end
176
+
177
+ def update_dependent_semvers product, semver_location, semver_file, dimension
178
+ semver_project_map = create_semver_project_map product, semver_location
179
+ projects_dependencies = get_project_dependencies semver_project_map[semver_file]
180
+ semver_files = get_project_dependencies_semver_files projects_dependencies, semver_project_map
181
+ semver_files.each { |semver|
182
+ increment_version File.join(semver_location, semver), dimension
183
+ }
184
+ end
185
+
186
+ def create_semver_project_map product, semver_location
187
+ semver_project_map = Hash.new
188
+
189
+ rake_list = get_file_list semver_location, 'semver'
190
+ rake_list.each{ |rakefile|
191
+ rake = rakefile.gsub "#{semver_location}/", ''
192
+ project_name = rake.gsub '.semver', ''
193
+ semver_project_map[rake] = "#{product}.#{project_name}.csproj"
194
+ }
195
+ semver_project_map
196
+ end
197
+
198
+ # Increment the major, minor, or patch of the .semver file.
199
+ def increment_version semver_file, dimension
200
+ if dimension.nil?
201
+ raise 'The parameter dimension is required to be one of : major | minor | patch'
202
+ end
203
+ semver = load_semver semver_file
204
+
205
+ case dimension
206
+ when 'major'
207
+ semver.major += 1
208
+ semver.minor = 0
209
+ semver.patch = 0
210
+ when 'minor'
211
+ semver.minor += 1
212
+ semver.patch = 0
213
+ when 'patch'
214
+ semver.patch += 1
215
+ else
216
+ raise "The parameter #{dimension} is invalid: major | minor | patch"
217
+ end
218
+
219
+ hash = "---\n:major: %s\n:minor: %s\n:patch: %s\n:special: '%s'\n:metadata: '%s'"
220
+ value = hash % [semver.major, semver.minor, semver.patch, semver.special, semver.metadata]
221
+ File.write semver_file, value
222
+ end
223
+
224
+ #load a sepcific semver (rather than generic .semver file
225
+ def load_semver path
226
+ v = SemVer.new
227
+ v.load path
228
+ v
229
+ end
230
+
231
+ #get list of semver files for given project list
232
+ def get_project_dependencies_semver_files projects_dependencies, semver_project_map
233
+ project_semver_map = semver_project_map.invert
234
+ @values = Array.new
235
+ projects_dependencies.each { |dependency|
236
+ if semver_project_map.value?(dependency)
237
+ @values << project_semver_map[dependency]
238
+ end
239
+ }
240
+ @values
241
+ end
242
+
243
+
244
+ #Find a given csproj reference in other projects in the solution
245
+ def get_project_dependencies csproj
246
+ proj_files = Dir.glob '**/*.csproj'
247
+ @unique_list = Array.new
248
+ proj_files.each{ |file|
249
+ doc = Nokogiri::XML File.read file
250
+ nodes = doc.search 'ProjectReference'
251
+ nodes.each { |node|
252
+ ref_val = node['Include']
253
+ id = ref_val.split('\\')[2]
254
+ if id.eql? csproj
255
+ @unique_list << file.split('/')[2]
256
+ end
257
+ }
258
+ }
259
+ @unique_list.uniq
260
+ end
261
+
262
+ def get_file_list path, extension
263
+ return Dir.glob("#{path}/*.#{extension}")
264
+ end
265
+
266
+ end
267
+
268
+ def auto_update_semver project_name, semver_location, semver_file, semver_dimension
269
+ versioning = SemverVersioning.new
270
+ versioning.auto_update_semver project_name, semver_location, semver_file, semver_dimension
271
+ end
272
+
273
+ def auto_update_local_semver
274
+ versioning = SemverVersioning.new
275
+ versioning.auto_update_local_semver
276
+ end
277
+
278
+ def is_team_city_run
279
+ ENV['BUILD_VCS_NUMBER'] != nil
280
+ end