Class: Metasploit::Version::CLI

Inherits:
Thor
  • Object
show all
Includes:
Thor::Actions
Defined in:
lib/metasploit/version/cli.rb

Overview

Command-line interface for metasploit-version. Used to run commands for managing the semantic version of a project.

Constant Summary collapse

GEM_NAME =

Name of this gem, for use in other projects that call metasploit-version install.

'metasploit-version'
DEVELOPMENT_DEPENDENCY_REGEXP =

Matches pre-existing development dependency on metasploit-version for updating.

/spec\.add_development_dependency\s+(?<quote>"|')#{GEM_NAME}\k<quote>/

Instance Method Summary collapse

Instance Method Details

#capitalize(word) ⇒ String (private)

Capitalizes words by converting the first character of word to upper case.

Parameters:

  • word (String)

    a lower case string

Returns:

  • (String)


113
114
115
# File 'lib/metasploit/version/cli.rb', line 113

def capitalize(word)
  word[0, 1].upcase + word[1 .. -1]
end

#development_dependency_lineString (private)

The line injected into the gemspec by #ensure_development_dependency

Returns:

  • (String)


120
121
122
# File 'lib/metasploit/version/cli.rb', line 120

def development_dependency_line
  "  spec.add_development_dependency '#{GEM_NAME}', '#{version_requirement}'\n"
end

#ensure_development_dependencyvoid (private)

This method returns an undefined value.

Ensures that the #gemspec_path contains a development dependency on GEM_NAME.

Adds spec.add_development_dependency 'metasploit_version', '~> <semantic version requirement>' if #gemspec_path does not have such an entry. Otherwise, updates the <semantic version requirement> to match this version of metasploit-version.

Raises:

  • (SystemExit)

    if no gemspec is found



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/metasploit/version/cli.rb', line 132

def ensure_development_dependency
  path = gemspec_path
  gem_specification = Gem::Specification.load(path)

  metasploit_version = gem_specification.dependencies.find { |dependency|
    dependency.name == GEM_NAME
  }

  lines = []

  if metasploit_version
    if metasploit_version.requirements_list.include? '>= 0'
      shell.say "Adding #{GEM_NAME} as a development dependency to "
    else
      shell.say "Updating #{GEM_NAME} requirements in "
    end

    shell.say path

    File.open(path) do |f|
      f.each_line do |line|
        match = line.match(DEVELOPMENT_DEPENDENCY_REGEXP)

        if match
          lines << development_dependency_line
        else
          lines << line
        end
      end
    end
  else
    end_index = nil
    lines = []

    open(path) do |f|
      line_index = 0

      f.each_line do |line|
        lines << line

        if line =~ /^\s*end\s*$/
          end_index = line_index
        end

        line_index += 1
      end
    end

    lines.insert(end_index, development_dependency_line)
  end

  File.open(path, 'w') do |f|
    lines.each do |line|
      f.write(line)
    end
  end
end

#gemspec_pathString (private)

The name of the gemspec in the current working directory.

Returns:

  • (String)

    relative path to the current working directory's gemspec.

Raises:

  • (SystemExit)

    if no gemspec is found



194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/metasploit/version/cli.rb', line 194

def gemspec_path
  unless instance_variable_defined? :@gemspec
    path = "#{name}.gemspec"

    unless File.exist?(path)
      shell.say 'No gemspec found'
      exit 1
    end

    @gemspec_path = path
  end

  @gemspec_path
end

#github_urlString (private)

The URL of the github repository. Used to calculate the fork and issues URL in CONTRIBUTING.md.

Returns:

  • (String)

    https url to github repository



212
213
214
# File 'lib/metasploit/version/cli.rb', line 212

def github_url
  @github_url ||= "https://github.com/#{options[:github_owner]}/#{name}"
end

#installvoid

This method returns an undefined value.

Adds 'metasploit-version' as a development dependency in this project's gemspec.



96
97
98
99
100
101
102
103
104
105
# File 'lib/metasploit/version/cli.rb', line 96

def install
  ensure_development_dependency
  template('lib/versioned/version.rb.tt', "lib/#{namespaced_path}/version.rb")
  install_bundle
  template('CHANGELOG.md.tt', 'CHANGELOG.md')
  template('CONTRIBUTING.md.tt', 'CONTRIBUTING.md')
  template('RELEASING.md.tt', 'RELEASING.md')
  template('UPGRADING.md.tt', 'UPGRADING.md')
  setup_rspec
end

#install_bundlevoid (private)

This method returns an undefined value.

bundle install if the :bundle_install options is true



219
220
221
222
223
# File 'lib/metasploit/version/cli.rb', line 219

def install_bundle
  if options[:bundle_install]
    system('bundle', 'install')
  end
end

#nameString (private)

The name of the gem.

Returns:

  • (String)

    name of the gem. Assumed to be the name of the pwd as it should match the repository name.



228
229
230
# File 'lib/metasploit/version/cli.rb', line 228

def name
  @name ||= File.basename(Dir.pwd)
end

#namespace_nameObject (private)

The fully-qualified namespace for the gem.

Parameters:

  • (String)


235
236
237
# File 'lib/metasploit/version/cli.rb', line 235

def namespace_name
  @namespace_name ||= namespaces.join('::')
end

#namespaced_pathString (private)

The relative path of the gem under lib.

Returns:

  • (String)

    Format of [<parent>/]*<child>



262
263
264
# File 'lib/metasploit/version/cli.rb', line 262

def namespaced_path
  @namespaced_path ||= name.tr('-', '/')
end

#namespacesArray<String> (private)

List of Module#names making up the the fully-qualifed namespace for the gem.

Returns:

  • (Array<String>)


242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/metasploit/version/cli.rb', line 242

def namespaces
  unless instance_variable_defined? :@namespaces
    underscored_words = name.split('_')
    capitalized_underscored_words = underscored_words.map { |underscored_word|
      capitalize(underscored_word)
    }
    capitalized_hyphenated_name = capitalized_underscored_words.join
    hyphenated_words = capitalized_hyphenated_name.split('-')

    @namespaces = hyphenated_words.map { |hyphenated_word|
      capitalize(hyphenated_word)
    }
  end

  @namespaces
end

#prereleasenil, String (private)

The prerelease version.

Returns:

  • (nil)

    if on master or HEAD

  • (String)

    if on a branch



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/metasploit/version/cli.rb', line 270

def prerelease
  unless instance_variable_defined? :@prerelease
    branch = Metasploit::Version::Branch.current
    parsed = Metasploit::Version::Branch.parse(branch)

    if parsed.is_a? Hash
      prerelease = parsed[:prerelease]

      if prerelease
        @prerelease = prerelease
      end
    end
  end

  @prerelease
end

#setup_rspecvoid (private)

This method returns an undefined value.

Generates .rspec, Rakefile, version_spec.rb, <namespace>_spec.rb and spec/spec_helper.rb



290
291
292
293
294
295
296
# File 'lib/metasploit/version/cli.rb', line 290

def setup_rspec
  template('.rspec.tt', '.rspec')
  template('Rakefile.tt', 'Rakefile')
  template('spec/lib/versioned/version_spec.rb.tt', "spec/#{version_path.sub(/\.rb$/, '_spec.rb')}")
  template('spec/lib/versioned_spec.rb.tt', "spec/lib/#{namespaced_path}_spec.rb")
  template('spec/spec_helper.rb.tt', 'spec/spec_helper.rb')
end

#version_pathString (private)

Path to the version.rb for the gem.

Returns:

  • (String)


301
302
303
# File 'lib/metasploit/version/cli.rb', line 301

def version_path
  @version_path ||= "lib/#{namespaced_path}/version.rb"
end

#version_requirementString (private)

The version requirement on the metasploit-version development dependency in #development_dependency_line.

Returns:

  • (String)


308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/metasploit/version/cli.rb', line 308

def version_requirement
  if defined? Metasploit::Version::Version::PRERELEASE
    # require exactly this pre-release in case there are multiple prereleases for the same
    # version number due to parallel branches.
    "= #{Metasploit::Version::GEM_VERSION}"
  elsif Metasploit::Version::Version::MAJOR < 1
    # can only allow the PATCH to wiggle pre-1.0.0
    "~> #{Metasploit::Version::Version::MAJOR}.#{Metasploit::Version::Version::MINOR}.#{Metasploit::Version::Version::PATCH}"
  else
    # can allow the MINOR to wiggle 1.0.0+
    "~> #{Metasploit::Version::Version::MAJOR}.#{Metasploit::Version::Version::MINOR}"
  end
end