Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/psdk/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ class Main < Thor
package_name 'psdk-cli'

desc 'version', 'show the psdk-cli version'
method_option :no_psdk_version, type: :boolean, aliases: '--no-psdk-version',
desc: 'do not search and show PSDK version'
def version
puts "psdk-cli v#{VERSION}"
require_relative 'helpers/version'
Version.run(options[:no_psdk_version])
end

desc 'plugin', 'manage PSDK plugins'
Expand Down
8 changes: 8 additions & 0 deletions lib/psdk/cli/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def get(type)

# Save the configuration
def save
make_config_global_dir
File.write(GLOBAL_CONFIGURATION_FILENAME, YAML.dump(@global.to_h))
return unless @local && @project_path

Expand All @@ -105,6 +106,13 @@ def save

private

def make_config_global_dir
dirname = File.dirname(GLOBAL_CONFIGURATION_FILENAME)
return if Dir.exist?(dirname)

Dir.mkdir(dirname)
end

def load_hash(path)
return {} unless File.exist?(path)

Expand Down
82 changes: 82 additions & 0 deletions lib/psdk/helpers/studio.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# frozen_string_literal: true

require_relative '../cli/configuration'

module Psdk
module Cli
# Module holding all the logic about the Pokémon Studio
module Studio
module_function

# Find and Save Pokemon studio path
def find_and_save_path
locations = common_studio_location.select { |l| Dir.exist?(l) }
binaries_locations = psdk_binaries_locations
studio_path = locations.find { |l| binaries_locations.any? { |b| Dir.exist?(File.join(l, b)) } }
return ask_and_save_studio_path unless studio_path

puts "\rLocated Pokemon Studio in `#{studio_path}`"
Configuration.get(:global).studio_path = studio_path
Configuration.save
end

# Get the PSDK binary path based on Studio path
# @param path [String]
# @return [String | nil]
def psdk_binaries_path(path)
valid_path = psdk_binaries_locations.find { |l| Dir.exist?(File.join(path, l)) }
return nil unless valid_path

return File.join(path, valid_path)
end

# Ask and save Pokemon Studio path
def ask_and_save_studio_path
print "\rCould not automatically find Pokémon Studio path, please enter it:"
path = $stdin.gets.chomp
check_psdk_binaries_in_provided_location(path)
Configuration.get(:global).studio_path = path
Configuration.save
rescue ArgumentError
retry
end

# Check if a provided path contains the psdk-binaries
# @param path [String]
def check_psdk_binaries_in_provided_location(path)
return if psdk_binaries_locations.any? { |l| Dir.exist?(File.join(path, l)) }

puts 'Provided path does not contain psdk-binaries'
raise ArgumentError
end

# Get all the common Pokemon Studio location
# @return [Array<String>]
def common_studio_location
volumes = Dir['/Volumes/**'] + Dir['/dev/sd*']
return [
'/Applications/PokemonStudio.app',
*(ENV['AppData'] ? studio_app_data_location : nil),
*volumes.map { |v| File.join(v, 'projects', 'PokemonStudio') },
'C:/Projects/PokemonStudio'
]
end

# Get all the psdk-binaries common location in Studio
# @return [Array<String>]
def psdk_binaries_locations
return [
'psdk-binaries',
'Contents/Resources/psdk-binaries',
'resources/psdk-binaries'
]
end

# Get the location of Studio in appdata
# @return [String]
def studio_app_data_location
return File.join(ENV.fetch('AppData', '.'), '../Local/Programs/pokemon-studio')
end
end
end
end
101 changes: 101 additions & 0 deletions lib/psdk/helpers/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# frozen_string_literal: true

require_relative '../cli/configuration'
require_relative 'studio'

module Psdk
module Cli
# Module holding all the logic about the version command
module Version
module_function

# Run the version command
# @param no_psdk_version [Boolean] do not show PSDK version if true
def run(no_psdk_version)
puts "psdk-cli v#{VERSION}"
return if no_psdk_version

print 'Searching for PSDK version...'
search_and_show_psdk_version
end

# Search and show the PSDK version
def search_and_show_psdk_version
search_and_show_global_psdk_version
search_and_show_local_psdk_version
end

# Search and show the global PSDK version
def search_and_show_global_psdk_version
global_config = Configuration.get(:global)
Studio.find_and_save_path if global_config.studio_path.empty?
psdk_binaries_path = Studio.psdk_binaries_path(global_config.studio_path)
return show_global_psdk_version(psdk_binaries_path) if psdk_binaries_path

puts "\r[Error] Current Pokemon Studio path does not contain psdk-binaries"
global_config.studio_path = ''
raise ArgumentError
rescue ArgumentError
retry
end

# Show the global PSDK version
# @param psdk_binaries_path [String]
def show_global_psdk_version(psdk_binaries_path)
version_string = version_to_string(load_version_integer(File.join(psdk_binaries_path, 'pokemonsdk')))
puts "\rGlobal PSDK version: #{version_string} "
end

# Search and show the local PSDK version
def search_and_show_local_psdk_version
Configuration.get(:local)
return unless Configuration.project_path

psdk_path = File.join(Configuration.project_path, 'pokemonsdk')
return show_no_local_psdk_version unless Dir.exist?(psdk_path)

version_string = version_to_string(load_version_integer(psdk_path))
puts "Project PSDK version: #{version_string}"
git_data = load_git_data(psdk_path)
puts "Project's PSDK git target: #{git_data}" unless git_data.empty?
end

# Show that there's no local PSDK version
def show_no_local_psdk_version
puts "Project PSDK Version: Studio's PSDK version"
end

# Load the Git data if any
# @param path [String] path to the PSDK installation
# @return [String]
def load_git_data(path)
Dir.chdir(path) do
return '' unless Dir.exist?('.git') || Dir.exist?('../.git')

commit = `git log --oneline -n 1`
branch = `git branch --show-current`
return "[#{branch}] #{commit}" unless branch.empty?

return "[!detached] #{commit}"
end
end

# Convert a version integer to a version string
# @param version [Integer]
# @return [String]
def version_to_string(version)
return [version].pack('I>').unpack('C*').join('.').gsub(/^(0\.)+/, '')
end

# Get the version integer from a path
# @param path [String] path where PSDK repository is
# @return [Integer]
def load_version_integer(path)
filename = File.join(path, 'version.txt')
return 0 unless File.exist?(filename)

return File.read(filename).to_i
end
end
end
end
3 changes: 2 additions & 1 deletion spec/psdk/cli/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

it 'loads an empty configuration if neither global or local file exists' do
expect(File).to receive(:read).exactly(0).times
allow(File).to receive(:exist?).and_return(false)

global = Psdk::Cli::Configuration.get(:global)
local = Psdk::Cli::Configuration.get(:local)
Expand Down Expand Up @@ -133,7 +134,7 @@
it 'successfully saves the configurations' do
stub_const('Psdk::Cli::Configuration::GLOBAL_CONFIGURATION_FILENAME', 'tmp/global.yml')
allow(File).to receive(:exist?) { |filename| filename.end_with?('/project.studio') }
allow(Dir).to receive(:exist?) { |filename| filename.start_with?('tmp/') }
allow(Dir).to receive(:exist?) { |filename| filename.start_with?('tmp/') || filename.end_with?('tmp') }

global = Psdk::Cli::Configuration.get(:global)
local = Psdk::Cli::Configuration.get(:local)
Expand Down
121 changes: 121 additions & 0 deletions spec/psdk/helpers/studio_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# frozen_string_literal: true

# rubocop:disable Metrics/BlockLength
RSpec.describe Psdk::Cli::Studio do
it 'provides Studio location in AppData' do
expect(ENV).to receive(:fetch).with('AppData', '.').and_return('C:/Users/User/AppData/Roaming')

expect(Psdk::Cli::Studio.studio_app_data_location).to eq(
'C:/Users/User/AppData/Roaming/../Local/Programs/pokemon-studio'
)
end

it 'provides all common locations' do
expect(ENV).to receive(:fetch).with('AppData', '.').and_return('C:/Users/User/AppData/Roaming')
allow(ENV).to receive(:[]).with('AppData').and_return('C:/Users/User/AppData/Roaming')
allow(Dir).to receive(:[]) { |path| path.include?('Volumes') ? ['/Volumes/HDD'] : ['/dev/sda1'] }

options = ['/Applications/PokemonStudio.app', 'C:/Users/User/AppData/Roaming/../Local/Programs/pokemon-studio',
'/Volumes/HDD/projects/PokemonStudio', '/dev/sda1/projects/PokemonStudio',
'C:/Projects/PokemonStudio']
expect(Psdk::Cli::Studio.common_studio_location).to eq(options)
end

it 'provides few common locations' do
allow(ENV).to receive(:[]).with('AppData').and_return(nil)
allow(Dir).to receive(:[]) { [] }

options = ['/Applications/PokemonStudio.app', 'C:/Projects/PokemonStudio']
expect(Psdk::Cli::Studio.common_studio_location).to eq(options)
end

it 'checks if psdk-binaries exists in provided location' do
allow(Dir).to receive(:exist?) { |path| path == '/path/resources/psdk-binaries' }

expect { Psdk::Cli::Studio.check_psdk_binaries_in_provided_location('/path') }.not_to raise_error
end

it 'raises ArgumentError if the psdk-binaries does not exists in provided location' do
allow(Dir).to receive(:exist?) { false }
expect(Psdk::Cli::Studio).to receive(:puts).with('Provided path does not contain psdk-binaries')

expect { Psdk::Cli::Studio.check_psdk_binaries_in_provided_location('/path') }.to raise_error(ArgumentError)
end

it 'asks for Studio path' do
configuration = Psdk::Cli::Configuration.new({})
allow(Dir).to receive(:exist?) { |path| path == '/path/resources/psdk-binaries' }
allow($stdin).to receive(:gets).and_return("/path\n")
expect(Psdk::Cli::Studio).to receive(:print).with(
"\rCould not automatically find Pokémon Studio path, please enter it:"
)
expect(Psdk::Cli::Configuration).to receive(:get).with(:global).and_return(configuration)
expect(configuration).to receive(:studio_path=).with('/path')
expect(Psdk::Cli::Configuration).to receive(:save)

Psdk::Cli::Studio.ask_and_save_studio_path
end

it 'asks for Studio path until a valid one is provided' do
configuration = Psdk::Cli::Configuration.new({})
i = 0
allow(Dir).to receive(:exist?) { |path| path == '/valid_path/resources/psdk-binaries' }
allow($stdin).to receive(:gets) { (i += 1) == 1 ? "/path\n" : "/valid_path\n" }
expect(Psdk::Cli::Studio).to receive(:puts).with('Provided path does not contain psdk-binaries').exactly(1).times
expect(Psdk::Cli::Studio).to(
receive(:print).with("\rCould not automatically find Pokémon Studio path, please enter it:").exactly(2).times
)
expect(Psdk::Cli::Configuration).to receive(:get).with(:global).and_return(configuration).exactly(1).times
expect(configuration).to receive(:studio_path=).with('/valid_path')
expect(Psdk::Cli::Configuration).to receive(:save)

Psdk::Cli::Studio.ask_and_save_studio_path
end

it 'returns the psdk-binaries path based on studio path' do
allow(Dir).to receive(:exist?) { |path| path == '/path/resources/psdk-binaries' }

expect(Psdk::Cli::Studio.psdk_binaries_path('/path')).to eq('/path/resources/psdk-binaries')
end

it 'returns nil as psdk-binaries path if none match' do
allow(Dir).to receive(:exist?) { false }

expect(Psdk::Cli::Studio.psdk_binaries_path('/path')).to eq(nil)
end

it 'finds the Studio path' do
configuration = Psdk::Cli::Configuration.new({})
valid_paths = ['/Applications/PokemonStudio.app',
'/Applications/PokemonStudio.app/Contents/Resources/psdk-binaries']
allow(Dir).to receive(:exist?) { |path| valid_paths.include?(path) }
expect(Psdk::Cli::Studio).to receive(:puts).with("\rLocated Pokemon Studio in `/Applications/PokemonStudio.app`")
expect(Psdk::Cli::Configuration).to receive(:get).with(:global).and_return(configuration)
expect(configuration).to receive(:studio_path=).with('/Applications/PokemonStudio.app')
expect(Psdk::Cli::Configuration).to receive(:save)

Psdk::Cli::Studio.find_and_save_path
end

it 'ask Studio path if target folder does not contains psdk-binaries' do
valid_paths = ['/Applications/PokemonStudio.app']
allow(Dir).to receive(:exist?) { |path| valid_paths.include?(path) }
expect(Psdk::Cli::Studio).not_to receive(:puts)
expect(Psdk::Cli::Configuration).not_to receive(:get).with(:global)
expect(Psdk::Cli::Configuration).not_to receive(:save)
expect(Psdk::Cli::Studio).to receive(:ask_and_save_studio_path)

Psdk::Cli::Studio.find_and_save_path
end

it 'ask Studio path if no common path is found' do
allow(Dir).to receive(:exist?) { false }
expect(Psdk::Cli::Studio).not_to receive(:puts)
expect(Psdk::Cli::Configuration).not_to receive(:get).with(:global)
expect(Psdk::Cli::Configuration).not_to receive(:save)
expect(Psdk::Cli::Studio).to receive(:ask_and_save_studio_path)

Psdk::Cli::Studio.find_and_save_path
end
end
# rubocop:enable Metrics/BlockLength
Loading