headdesk 0.10.0 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9067a4b373fd01b502fd6cb77fafc2bd1c60e9d18aef42390832e855bf6437e8
4
- data.tar.gz: 3eccbb70deffe105e84a5ae0bfd6aecf8977ae9d9399665863570681fa92933a
3
+ metadata.gz: 1cb06518f9ed0ec0293c645af5598133a19791c575093359b56cf87e787233de
4
+ data.tar.gz: 6a0bd907a2c18c63098029cb30956c8ebe903529b34738cf61a2b1b61d3b0983
5
5
  SHA512:
6
- metadata.gz: 046264add67d0b39f07a5d57eb95372fd5b0ba5278443c17768aade9932a3c2a868454f25a239df242644f61b4ec766370aed860ef8944a64012c8de6726dace
7
- data.tar.gz: eac8f28b1aa2ddc80bb30369f9b384dc2c6928a611720b16b914705498d448feaa10e66a90cf19c98e646f64d17595f33df2d3d24e2468f2eeeb3249c0082f87
6
+ metadata.gz: bf63bee2c75af483978333022c08fcdcdd61d3abab31f979445ef2766287baf9a750d3303e9538358d29c7152ea44e76a8a0aadd429cf8a671f7b4b6c4ef0f00
7
+ data.tar.gz: 20d878b5cf28dbe13ad88b838143a9da3ca62ee3693b39db205c2975f3edecc3f1e81ca9ef1657c1efa9052446e299c59bcd50c9672d6dcf7655637b097c73a5
data/.reek.yml CHANGED
@@ -5,6 +5,8 @@ detectors:
5
5
  - 'apk.resources'
6
6
  - 'Thor::Base.shell'
7
7
  - 'CLI.command_help'
8
+ - 'exit'
8
9
  TooManyStatements:
9
10
  exclude:
10
11
  - 'Headdesk::Checks'
12
+ - 'Headdesk::CliCommands'
data/Gemfile CHANGED
@@ -4,8 +4,5 @@ source 'https://rubygems.org'
4
4
 
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
- gem 'reek'
8
- gem 'rubocop'
9
-
10
7
  # Specify your gem's dependencies in headdesk.gemspec
11
8
  gemspec
data/Gemfile.lock CHANGED
@@ -26,6 +26,7 @@ GEM
26
26
  thread_safe (~> 0.3, >= 0.3.1)
27
27
  diff-lcs (1.3)
28
28
  equalizer (0.0.11)
29
+ gem-release (2.0.1)
29
30
  gems (1.1.1)
30
31
  json
31
32
  ice_nine (0.11.2)
@@ -37,7 +38,7 @@ GEM
37
38
  mini_portile2 (~> 2.4.0)
38
39
  oily_png (1.2.1)
39
40
  chunky_png (~> 1.3.7)
40
- parallel (1.12.1)
41
+ parallel (1.13.0)
41
42
  parser (2.5.3.0)
42
43
  ast (~> 2.4.0)
43
44
  powerpack (0.1.2)
@@ -63,7 +64,7 @@ GEM
63
64
  diff-lcs (>= 1.2.0, < 2.0)
64
65
  rspec-support (~> 3.8.0)
65
66
  rspec-support (3.8.0)
66
- rubocop (0.62.0)
67
+ rubocop (0.63.1)
67
68
  jaro_winkler (~> 1.5.1)
68
69
  parallel (~> 1.10)
69
70
  parser (>= 2.5, != 2.5.1.1)
@@ -86,11 +87,12 @@ PLATFORMS
86
87
 
87
88
  DEPENDENCIES
88
89
  bundler (~> 2.0)
90
+ gem-release (~> 2.0)
89
91
  headdesk!
90
92
  rake (~> 10.0)
91
- reek
93
+ reek (~> 5.0)
92
94
  rspec (~> 3.8)
93
- rubocop
95
+ rubocop (~> 0)
94
96
 
95
97
  BUNDLED WITH
96
98
  2.0.1
data/headdesk.gemspec CHANGED
@@ -17,15 +17,6 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  spec.post_install_message = 'For breaking change announcements...'
19
19
 
20
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
21
- # to allow pushing to a single host or delete this section to allow pushing to any host.
22
- # if spec.respond_to?(:metadata)
23
- # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
24
- # else
25
- # raise 'RubyGems 2.0 or newer is required to protect against ' \
26
- # 'public gem pushes.'
27
- # end
28
-
29
20
  # Specify which files should be added to the gem when it is released.
30
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
22
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
@@ -36,8 +27,11 @@ Gem::Specification.new do |spec|
36
27
  spec.require_paths = ['lib']
37
28
 
38
29
  spec.add_development_dependency 'bundler', '~> 2.0'
30
+ spec.add_development_dependency 'gem-release', '~> 2.0'
39
31
  spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'reek', '~> 5.0'
40
33
  spec.add_development_dependency 'rspec', '~> 3.8'
34
+ spec.add_development_dependency 'rubocop', '~> 0'
41
35
 
42
36
  spec.add_dependency 'awesome_print', '~> 1.8'
43
37
  spec.add_dependency 'gems', '~> 1.1'
data/lib/headdesk/cli.rb CHANGED
@@ -1,114 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'tmpdir'
4
3
  require 'thor'
5
4
  require 'headdesk'
6
5
  require 'awesome_print'
7
6
 
7
+ Dir[File.dirname(__FILE__) + '/cli_commands/*.rb'].each { |file| require file }
8
+
8
9
  module Headdesk
9
10
  #
10
11
  # headdesk CLI
11
12
  #
12
- # :reek:TooManyStatements
13
13
  class CLI < Thor
14
14
  no_commands do
15
- def print_update_message
16
- STDOUT.puts format("\e[36m%s\e[0m", "Latest version is #{Headdesk::Versions.latest_version}, please run 'bundle update headdesk'")
17
- end
18
- end
19
-
20
- desc 'unpack FILE [DESTINATION]', 'Unpack an APK or IPA to [DESTINATION] or to the current directory'
21
- method_option :analyze, type: :boolean, aliases: '-a'
22
- def unpack(file, destination = nil)
23
- # Make sure the input file exists
24
- unless File.exist?(file)
25
- STDERR.puts "Could not find: #{file}"
26
- CLI.command_help(Thor::Base.shell.new, 'unpack')
27
- return 1
28
- end
29
-
30
- # Make sure destination exists, if specified
31
- unless !destination || Dir.exist?(destination)
32
- STDERR.puts "Could not find destination path: #{destination}"
33
- CLI.command_help(Thor::Base.shell.new, 'unpack')
34
- return 1
35
- end
36
-
37
- begin
38
- stdout = nil
39
- output_path = destination
40
-
41
- if !destination
42
- # Output to tempdir, then copy to cwd if no destination specified
43
- Dir.mktmpdir do |tmp_dir|
44
- output_path = tmp_dir
45
- stdout = Headdesk::ApkTool.unpack_to(file, tmp_dir)
46
- FileUtils.cp_r("#{tmp_dir}/.", Dir.pwd)
47
- end
48
- else
49
- stdout = Headdesk::ApkTool.unpack_to(file, destination)
50
- end
51
-
52
- # analyze if requested
53
- Headdesk::Analyze.at(output_path) if options[:analyze]
54
- rescue CliError => cli_err
55
- STDERR.puts cli_err.message
56
- CLI.command_help(Thor::Base.shell.new, 'unpack')
57
- return 1
58
- rescue StandardError => rb_err
59
- STDERR.puts err.message.red
60
- STDERR.puts err.backtrace.ai
61
- return 1
15
+ def print_update_message(stream = STDERR)
16
+ stream.puts "Latest version is #{Headdesk::Versions.latest_version}, please run 'bundle update headdesk'".red
62
17
  end
63
18
  end
64
19
 
65
- desc 'analyze [FILE]', 'Analyze an APK or IPA'
66
- method_option :path, type: :string
67
- method_option :json, type: :boolean
68
- def analyze(file = nil)
69
- # Make sure input file exsts, if specified
70
- unless !file || File.exist?(file)
71
- STDERR.puts "Could not find input file: #{file}"
72
- CLI.command_help(Thor::Base.shell.new, 'analyze')
73
- return 1
74
- end
75
-
76
- # Unpack APK if needed
77
- path = options[:path]
78
- tmp_dir = nil
79
- if file
80
- path = tmp_dir = Dir.mktmpdir
81
- Headdesk::ApkTool.unpack_to(file, tmp_dir)
82
- end
83
-
84
- # Make sure path exists
85
- unless Dir.exist?(path)
86
- STDERR.puts "Could not find path: #{path}"
87
- CLI.command_help(Thor::Base.shell.new, 'analyze')
88
- return 1
89
- end
90
-
91
- # analyze
92
- begin
93
- report = Headdesk::Analyze.at(path)
94
-
95
- if options[:json]
96
- STDOUT.puts report.to_json
97
- else
98
- STDOUT.puts report.to_s
99
- print_update_message unless Headdesk::Versions.latest_version?
100
- end
101
- rescue CliError => cli_err
102
- STDERR.puts cli_err.message
103
- CLI.command_help(Thor::Base.shell.new, 'analyze')
104
- return 1
105
- rescue StandardError => err
106
- STDERR.puts err.message.red
107
- STDERR.puts err.backtrace.ai
108
- return 1
109
- end
110
- ensure
111
- FileUtils.remove_entry(tmp_dir) if tmp_dir
20
+ Headdesk::CliCommand.each do |cmd|
21
+ include cmd
112
22
  end
113
23
  end
114
24
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'headdesk'
5
+ require 'tmpdir'
6
+
7
+ module Headdesk
8
+ module CliCommands
9
+ #
10
+ # Analyze an APK/IPA file
11
+ #
12
+ module Analyze
13
+ include Headdesk::CliCommand
14
+
15
+ def self.included(thor)
16
+ thor.class_eval do
17
+ desc 'analyze [FILE]', 'Analyze an APK or IPA'
18
+ method_option :path, type: :string
19
+ method_option :json, type: :boolean
20
+ def analyze(file = nil)
21
+ # Make sure input file exsts, if specified
22
+ unless !file || File.exist?(file)
23
+ STDERR.puts "Could not find input file: #{file}"
24
+ CLI.command_help(Thor::Base.shell.new, 'analyze')
25
+ exit 1
26
+ end
27
+
28
+ # Unpack APK if needed
29
+ path = options[:path]
30
+ tmp_dir = nil
31
+ if file
32
+ path = tmp_dir = Dir.mktmpdir
33
+ Headdesk::ApkTool.unpack_to(file, tmp_dir)
34
+ end
35
+
36
+ # Make sure path exists
37
+ unless Dir.exist?(path)
38
+ STDERR.puts "Could not find path: #{path}"
39
+ CLI.command_help(Thor::Base.shell.new, 'analyze')
40
+ exit 1
41
+ end
42
+
43
+ # analyze
44
+ begin
45
+ report = Headdesk::Analyze.at(path)
46
+
47
+ if options[:json]
48
+ STDOUT.puts report.to_json
49
+ else
50
+ STDOUT.puts report.to_s
51
+ CLI.print_update_message unless Headdesk::Versions.latest_version?
52
+ end
53
+ rescue CliError => cli_err
54
+ STDERR.puts cli_err.message
55
+ CLI.command_help(Thor::Base.shell.new, 'analyze')
56
+ exit 1
57
+ rescue StandardError => err
58
+ STDERR.puts err.message.red
59
+ STDERR.puts err.backtrace.ai
60
+ exit 1
61
+ end
62
+ ensure
63
+ FileUtils.remove_entry(tmp_dir) if tmp_dir
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'headdesk'
5
+ require 'English'
6
+
7
+ module Headdesk
8
+ module CliCommands
9
+ #
10
+ # Find out which JAR/AAR is bringing in symbols
11
+ #
12
+ module Blame
13
+ include Headdesk::CliCommand
14
+
15
+ def self.included(thor)
16
+ thor.class_eval do
17
+ desc 'blame SYMBOL [PATH]', 'Recursivly search for JARs and AARs which define a given symbol.'
18
+ method_option :json, type: :boolean
19
+ def blame(in_symbol, path = '.')
20
+ unless Dir.exist?(path)
21
+ STDERR.puts "Could not find path: #{path}"
22
+ CLI.command_help(Thor::Base.shell.new, 'blame')
23
+ exit 1
24
+ end
25
+
26
+ symbol_matcher = /(.*)(#{Regexp.escape(in_symbol.tr('.', '/'))})([^\.]*)?(\.class)?/
27
+
28
+ # Match inside JAR files
29
+ jar_matches = {}
30
+ Dir[File.join(path, '**', '*.jar')].each do |jar|
31
+ stdout = `jar -tf #{jar}`
32
+ exit $CHILD_STATUS.to_i unless $CHILD_STATUS.success?
33
+
34
+ matches = Blame.match_lines(stdout, symbol_matcher)
35
+ jar_matches[jar] = matches unless matches.empty?
36
+ end
37
+
38
+ # Match inside AAR files
39
+ aar_matches = {}
40
+ Dir[File.join(path, '**', '*.aar')].each do |aar|
41
+ stdout = `unzip -p -j #{aar} classes.jar | jar -t`
42
+ exit $CHILD_STATUS.to_i unless $CHILD_STATUS.success?
43
+
44
+ matches = Blame.match_lines(stdout, symbol_matcher)
45
+ aar_matches[aar] = matches unless matches.empty?
46
+ end
47
+
48
+ # JSON output if requested
49
+ if options[:json]
50
+ STDOUT.puts({ jar: jar_matches, aar: aar_matches }.to_json)
51
+ exit 0
52
+ end
53
+
54
+ # Pretty output
55
+ all_matches = jar_matches.merge(aar_matches)
56
+ all_matches.each do |package, symbols|
57
+ STDOUT.puts '📦 ' + package
58
+ symbols.each do |match|
59
+ STDOUT.puts " ↳ #{match[0]}#{match[1].green}#{match[2].chomp('.') if match[2]}"
60
+ end
61
+ end
62
+
63
+ CLI.print_update_message unless Headdesk::Versions.latest_version?
64
+
65
+ exit !all_matches.empty?
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.match_lines(stdout, matcher)
71
+ stdout.lines
72
+ .each(&:strip!)
73
+ .map { |line| matcher.match(line) }
74
+ .compact
75
+ .map { |match| match.captures.map { |capture| capture.tr('/', '.') if capture } }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'headdesk'
5
+ require 'tmpdir'
6
+
7
+ module Headdesk
8
+ module CliCommands
9
+ #
10
+ # Unpack an APK/IPA
11
+ #
12
+ module Unpack
13
+ include Headdesk::CliCommand
14
+
15
+ def self.included(thor)
16
+ thor.class_eval do
17
+ desc 'unpack FILE [DESTINATION]', 'Unpack an APK or IPA to [DESTINATION] or to the current directory'
18
+ method_option :analyze, type: :boolean, aliases: '-a'
19
+ def unpack(file, destination = nil)
20
+ # Make sure the input file exists
21
+ unless File.exist?(file)
22
+ STDERR.puts "Could not find: #{file}"
23
+ CLI.command_help(Thor::Base.shell.new, 'unpack')
24
+ exit 1
25
+ end
26
+
27
+ # Make sure destination exists, if specified
28
+ unless !destination || Dir.exist?(destination)
29
+ STDERR.puts "Could not find destination path: #{destination}"
30
+ CLI.command_help(Thor::Base.shell.new, 'unpack')
31
+ exit 1
32
+ end
33
+
34
+ begin
35
+ stdout = nil
36
+ output_path = destination
37
+
38
+ if !destination
39
+ # Output to tempdir, then copy to cwd if no destination specified
40
+ Dir.mktmpdir do |tmp_dir|
41
+ output_path = tmp_dir
42
+ stdout = Headdesk::ApkTool.unpack_to(file, tmp_dir)
43
+ FileUtils.cp_r("#{tmp_dir}/.", Dir.pwd)
44
+ end
45
+ else
46
+ stdout = Headdesk::ApkTool.unpack_to(file, destination)
47
+ end
48
+
49
+ # analyze if requested
50
+ Headdesk::Analyze.at(output_path) if options[:analyze]
51
+
52
+ CLI.print_update_message unless Headdesk::Versions.latest_version?
53
+ rescue CliError => cli_err
54
+ STDERR.puts cli_err.message
55
+ CLI.command_help(Thor::Base.shell.new, 'unpack')
56
+ exit 1
57
+ rescue StandardError => rb_err
58
+ STDERR.puts err.message.red
59
+ STDERR.puts err.backtrace.ai
60
+ exit 1
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'headdesk'
5
+
6
+ module Headdesk
7
+ module CliCommands
8
+ #
9
+ # Print/compare version
10
+ #
11
+ module Version
12
+ include Headdesk::CliCommand
13
+
14
+ def self.included(thor)
15
+ thor.class_eval do
16
+ map %w[--version] => :__version
17
+ desc '--version [COMPARE_VERSION]', 'Print, and optionally compare version.'
18
+ long_desc <<~LONGDESC
19
+ `--version` will print the version to STDOUT, and if a newer version is available it will print out an update message to STDERR.
20
+
21
+ You can optionally specify a version number as a second argument, in which case will compare the current version with that version exit with code 1 if the current version is less than the provided version. It will exit with code 0 if the current version is less than, or equal to the provided version.
22
+ LONGDESC
23
+ def __version(cmp_version = nil)
24
+ STDOUT.puts Headdesk::VERSION
25
+ print_update_message unless Headdesk::Versions.latest_version?
26
+
27
+ exit (Headdesk::Versions.version <=> Gem::Version.new(cmp_version)) > 0 if cmp_version
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Headdesk
4
+ VERSION = '0.11.0'
4
5
  APKTOOL_VERSION = '2.3.4'
5
- VERSION = '0.10.0'
6
6
  end
@@ -7,6 +7,10 @@ module Headdesk
7
7
  # Version information from RubyGems.org
8
8
  #
9
9
  class Versions
10
+ def self.version
11
+ Gem::Version.new(VERSION)
12
+ end
13
+
10
14
  def self.versions
11
15
  Gems.versions('headdesk').collect do |version|
12
16
  Gem::Version.new(version['number'])
data/lib/headdesk.rb CHANGED
@@ -22,4 +22,20 @@ module Headdesk
22
22
  #
23
23
  class CliError < StandardError
24
24
  end
25
+
26
+ #
27
+ # Helper for CLI command modules
28
+ #
29
+ module CliCommand
30
+ extend Enumerable
31
+
32
+ def self.each(&block)
33
+ @commands.each(&block)
34
+ end
35
+
36
+ def self.included(cmd)
37
+ @commands ||= []
38
+ @commands << cmd
39
+ end
40
+ end
25
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: headdesk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Wilson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-21 00:00:00.000000000 Z
11
+ date: 2019-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gem-release
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,20 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: reek
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rspec
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,20 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '3.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: awesome_print
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -169,6 +211,10 @@ files:
169
211
  - lib/headdesk/checks/teak/caching.rb
170
212
  - lib/headdesk/checks/teak/teak.rb
171
213
  - lib/headdesk/cli.rb
214
+ - lib/headdesk/cli_commands/analyze.rb
215
+ - lib/headdesk/cli_commands/blame.rb
216
+ - lib/headdesk/cli_commands/unpack.rb
217
+ - lib/headdesk/cli_commands/version.rb
172
218
  - lib/headdesk/data/facebook_sdk_versions.yaml
173
219
  - lib/headdesk/descriptionator.rb
174
220
  - lib/headdesk/descriptionator/resources.rb