lib/apkstats/command/apk_analyzer.rb in danger-apkstats-0.0.2 vs lib/apkstats/command/apk_analyzer.rb in danger-apkstats-0.1.0

- old
+ new

@@ -1,35 +1,70 @@ -module Danger::Apkstats +# frozen_string_literal: true + +module Apkstats::Command class ApkAnalyzer - include Danger::Apkstats::ExecutableCommand + include Apkstats::Command::Executable - def compare_with(apk_filepath, other_apk_filepath) - out, err = run_command('apk', 'compare', '--different-only', apk_filepath, other_apk_filepath) + def initialize(opts) + @command_path = opts[:command_path] || "#{ENV.fetch('ANDROID_HOME')}/tools/bin/apkanalyzer" + end - if out - return out.partition("\n").first.strip, nil - else - return nil, err - end + def file_size(apk_filepath) + run_command("apk", "file-size", apk_filepath) end - def filesize(apk_filepath) - run_command('apk', 'file-size', apk_filepath) + def download_size(apk_filepath) + run_command("apk", "download-size", apk_filepath) end - def downloadsize(apk_filepath) - run_command('apk', 'download-size', apk_filepath) + def required_features(apk_filepath) + ::Apkstats::Entity::Features.new(ApkAnalyzer.parse_features(run_command("apk", "features", apk_filepath))) end - private + def non_required_features(apk_filepath) + all_features = ApkAnalyzer.parse_features(run_command("apk", "features", "--not-required", apk_filepath)) + Apkstats::Entity::Features.new(all_features.select(&:not_required?)) + end - def run_command(*args) - out, err, status = Open3.capture3("#{command} #{args.join(' ')}") - return out, nil if status == 0 - return nil, (err || 'failed due while executing a command') + def permissions(apk_filepath) + ::Apkstats::Entity::Permissions.new(ApkAnalyzer.parse_permissions(run_command("manifest", "permissions", apk_filepath))) end - def command - @command ||= "#{ENV.fetch('ANDROID_HOME')}/tools/bin/apkanalyzer" + def min_sdk(apk_filepath) + run_command("manifest", "min-sdk", apk_filepath) end + + def target_sdk(apk_filepath) + run_command("manifest", "target-sdk", apk_filepath) + end + + def self.parse_permissions(command_output) + command_output.split(/\r?\n/).map { |s| to_permission(s) } + end + + def self.to_permission(str) + # If maxSdkVersion is specified, the output is like `android.permission.INTERNET' maxSdkVersion='23` + name_seed, max_sdk_seed = str.strip.split(/\s/) + ::Apkstats::Entity::Permission.new(name_seed.gsub(/'$/, ""), max_sdk: max_sdk_seed && max_sdk_seed[/[0-9]+/]) + end + + def self.parse_features(command_output) + command_output.split(/\r?\n/).map { |s| to_feature(s) } + end + + def self.to_feature(str) + # format / name implied: xxxx + # not-required and implied cannot co-exist so it's okay to parse them like this + name, kind, tail = str.strip.split(/\s/, 3) + + ::Apkstats::Entity::Feature.new(name, not_required: kind == "not-required", implied_reason: kind == "implied:" && tail) + end + + private + + def run_command(*args) + out, err, status = Open3.capture3("#{command_path} #{args.join(' ')}") + raise err unless status.success? + out.rstrip + end end -end \ No newline at end of file +end