kosmos 0.0.1

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +15 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +21 -0
  6. data/Rakefile +2 -0
  7. data/bin/kosmos +93 -0
  8. data/kosmos.gemspec +24 -0
  9. data/lib/kosmos.rb +54 -0
  10. data/lib/kosmos/download_url.rb +76 -0
  11. data/lib/kosmos/git_adapter.rb +61 -0
  12. data/lib/kosmos/package.rb +119 -0
  13. data/lib/kosmos/package_dsl.rb +10 -0
  14. data/lib/kosmos/packages/active_texture_management.rb +20 -0
  15. data/lib/kosmos/packages/astronomers_visual_pack.rb +54 -0
  16. data/lib/kosmos/packages/b9_aerospace_pack.rb +22 -0
  17. data/lib/kosmos/packages/better_atmospheres.rb +41 -0
  18. data/lib/kosmos/packages/cacteye.rb +10 -0
  19. data/lib/kosmos/packages/deadly_reentry.rb +9 -0
  20. data/lib/kosmos/packages/distant_object_enhancement.rb +8 -0
  21. data/lib/kosmos/packages/docking_port_alignment_indicator.rb +8 -0
  22. data/lib/kosmos/packages/enhanced_navball.rb +8 -0
  23. data/lib/kosmos/packages/environmental_visual_enhancements.rb +22 -0
  24. data/lib/kosmos/packages/ferram_aerospace_research.rb +11 -0
  25. data/lib/kosmos/packages/firespitter.rb +8 -0
  26. data/lib/kosmos/packages/hot_rockets.rb +11 -0
  27. data/lib/kosmos/packages/infernal_robotics.rb +8 -0
  28. data/lib/kosmos/packages/kerbal_alarm_clock.rb +8 -0
  29. data/lib/kosmos/packages/kerbal_attachment_system.rb +9 -0
  30. data/lib/kosmos/packages/kerbal_engineer_redux.rb +8 -0
  31. data/lib/kosmos/packages/kerbal_joint_reinforcement.rb +8 -0
  32. data/lib/kosmos/packages/kethane_pack.rb +9 -0
  33. data/lib/kosmos/packages/ksp_interstellar.rb +10 -0
  34. data/lib/kosmos/packages/kw_rocketry.rb +8 -0
  35. data/lib/kosmos/packages/mechjeb.rb +8 -0
  36. data/lib/kosmos/packages/mk2_cockpit_interior.rb +8 -0
  37. data/lib/kosmos/packages/nova_punch.rb +10 -0
  38. data/lib/kosmos/packages/procedural_fairings.rb +8 -0
  39. data/lib/kosmos/packages/real_chute.rb +9 -0
  40. data/lib/kosmos/packages/remote_tech.rb +18 -0
  41. data/lib/kosmos/packages/safe_chute.rb +8 -0
  42. data/lib/kosmos/packages/scansat.rb +8 -0
  43. data/lib/kosmos/packages/spaceplane_plus.rb +9 -0
  44. data/lib/kosmos/packages/tac_fuel_balancer.rb +8 -0
  45. data/lib/kosmos/packages/tac_life_support.rb +9 -0
  46. data/lib/kosmos/packages/toolbar.rb +9 -0
  47. data/lib/kosmos/packages/vanguard_technologies.rb +18 -0
  48. data/lib/kosmos/page_fetcher.js +47 -0
  49. data/lib/kosmos/post_processors/module_manager_resolver.rb +30 -0
  50. data/lib/kosmos/util.rb +7 -0
  51. data/lib/kosmos/version.rb +3 -0
  52. data/lib/kosmos/versioner.rb +65 -0
  53. data/spec/download_url_spec.rb +64 -0
  54. data/spec/fixtures/example_box.html +165 -0
  55. data/spec/fixtures/example_dropbox.html +114 -0
  56. data/spec/fixtures/example_mediafire.html +101 -0
  57. data/spec/package_spec.rb +77 -0
  58. data/spec/spec_helper.rb +22 -0
  59. data/spec/versioner_spec.rb +87 -0
  60. metadata +166 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ad005bee0010cb3e081b6851874c9f568ad09149
4
+ data.tar.gz: 447b7bcda49ea3362b8343793da95b0ccbb084e0
5
+ SHA512:
6
+ metadata.gz: 51858f7b3d5d0eb5da764d05fd72ec4d7eab02c82e1061cbfce0ce5fd84faa1c2c874a549822bed30ab27d8a032f24b7cbdd2cecd781eb5b9081a5be18fe2be1
7
+ data.tar.gz: 1885d290b5215ab24537cf010c14ed9898d14698882553dc548a8bff886fc17accf6433aef6888f17e3da24f3307e30f190585a49da01c958daaa080ed0a41a8
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'bundler', '~> 1.6'
7
+ gem 'rake'
8
+ gem 'rspec', '~> 2.14'
9
+ gem 'webmock'
10
+ gem 'pry'
11
+ end
12
+
13
+ group :test do
14
+ gem 'fakefs', require: 'fakefs/safe'
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ulysse Carion
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Kosmos
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kosmos'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kosmos
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/kosmos ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'kosmos'
4
+
5
+ Kosmos.configure do |config|
6
+ config.verbose = true
7
+ end
8
+
9
+ def pretty_print_list(list)
10
+ list.each { |value| puts " * #{value}" }
11
+ end
12
+
13
+ def load_packages(package_names)
14
+ packages = Hash[package_names.map do |name|
15
+ [name, Kosmos::Package.find(name)]
16
+ end]
17
+
18
+ unknown_packages = packages.select { |_, package| package.nil? }
19
+
20
+ if unknown_packages.any?
21
+ puts "Error: Kosmos couldn't find any packages with the following names:"
22
+ pretty_print_list(unknown_packages.keys)
23
+ exit
24
+ end
25
+
26
+ packages.values
27
+ end
28
+
29
+ def check_installed_packages(ksp_path, packages)
30
+ installed_titles = Kosmos::Versioner.installed_packages(ksp_path)
31
+
32
+ installed_packages = packages.select do |package|
33
+ installed_titles.include?(package.title)
34
+ end
35
+
36
+ if installed_packages.any?
37
+ puts "Error: You have already installed the following packages using Kosmos:"
38
+ pretty_print_list(installed_packages.map(&:title))
39
+ exit
40
+ end
41
+ end
42
+
43
+ case ARGV.shift
44
+ when 'init'
45
+ ksp_path = ARGV.shift
46
+
47
+ puts "Initializing Kosmos into #{ksp_path} (This will take a sec) ..."
48
+
49
+ Kosmos::Versioner.init_repo(ksp_path)
50
+ Kosmos.save_ksp_path(ksp_path)
51
+
52
+ puts "Done! You're ready to begin installing mods."
53
+ puts
54
+ puts "Install your first mod by running the command:"
55
+ puts " kosmos install [name-of-the-mod]"
56
+ puts
57
+
58
+ when 'install'
59
+ ksp_path = Kosmos.load_ksp_path
60
+
61
+ packages = load_packages(ARGV)
62
+ check_installed_packages(ksp_path, packages)
63
+
64
+ puts "Kosmos is about to install #{packages.count} package(s):"
65
+ pretty_print_list(packages.map(&:title))
66
+
67
+ packages.each do |package|
68
+ puts "Installing package #{package.title} ..."
69
+ package.new.install!(ksp_path)
70
+ puts "Done!"
71
+ end
72
+
73
+ when 'uninstall'
74
+ ksp_path = Kosmos.load_ksp_path
75
+
76
+ package_name = ARGV.shift
77
+ package = Kosmos::Package.find(package_name)
78
+
79
+ if package
80
+ puts "Preparing to uninstall #{package.title} ..."
81
+ Kosmos::Versioner.uninstall_package(ksp_path, package)
82
+ puts "Done! Just uninstalled: #{package.title}."
83
+ else
84
+ puts "Error: Kosmos couldn't find any packages with the name #{package_name.inspect}."
85
+ end
86
+
87
+ when 'list'
88
+ ksp_path = Kosmos.load_ksp_path
89
+
90
+ packages = Kosmos::Versioner.installed_packages(ksp_path)
91
+ puts "You have installed #{packages.length} mod(s) using Kosmos:"
92
+ pretty_print_list(packages)
93
+ end
data/kosmos.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kosmos/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kosmos"
8
+ spec.version = Kosmos::VERSION
9
+ spec.authors = ["Ulysse Carion"]
10
+ spec.email = ["ulyssecarion@gmail.com"]
11
+ spec.summary = %q{The simple package manager for Kerbal Space Program.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "rubyzip"
21
+ spec.add_dependency "rugged"
22
+ spec.add_dependency "httparty"
23
+ spec.add_dependency "nokogiri"
24
+ end
data/lib/kosmos.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'kosmos/package_dsl'
2
+ require 'kosmos/package'
3
+ require 'kosmos/versioner'
4
+ require 'kosmos/git_adapter'
5
+ require 'kosmos/download_url'
6
+ require 'kosmos/util'
7
+ require 'kosmos/version'
8
+
9
+ require 'json'
10
+
11
+ module Kosmos
12
+ class << self
13
+ def config
14
+ @config ||= Configuration.new
15
+ end
16
+
17
+ def configure
18
+ yield(config)
19
+ end
20
+
21
+ def save_ksp_path(path)
22
+ write_config(ksp_path: path)
23
+ end
24
+
25
+ def load_ksp_path
26
+ read_config[:ksp_path]
27
+ end
28
+
29
+ private
30
+
31
+ def write_config(opts)
32
+ File.open(config_path, "rw+") do |file|
33
+ file.write JSON.pretty_generate(read_config.merge(opts))
34
+ end
35
+ end
36
+
37
+ def read_config
38
+ JSON.parse(File.read(config_path), symbolize_names: true)
39
+ end
40
+
41
+ def config_path
42
+ File.join(Dir.home, ".kosmos")
43
+ end
44
+ end
45
+
46
+ class Configuration
47
+ attr_accessor :verbose, :post_processors
48
+
49
+ def initialize
50
+ @verbose = false
51
+ @post_processors = [Kosmos::PostProcessors::ModuleManagerResolver]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,76 @@
1
+ require 'nokogiri'
2
+
3
+ module Kosmos
4
+ class DownloadUrl < Struct.new(:url)
5
+ def resolve_download_url
6
+ if mediafire?
7
+ extract_mediafire_url
8
+ elsif box?
9
+ extract_box_url
10
+ elsif dropbox?
11
+ extract_dropbox_url
12
+ elsif curseforge?
13
+ extract_curseforge_url
14
+ else
15
+ url
16
+ end
17
+ end
18
+
19
+ def mediafire?
20
+ url =~ /mediafire/
21
+ end
22
+
23
+ def box?
24
+ url =~ /app\.box\.com/
25
+ end
26
+
27
+ def dropbox?
28
+ url =~ /dropbox/
29
+ end
30
+
31
+ def curseforge?
32
+ url =~ /curseforge/
33
+ end
34
+
35
+ private
36
+
37
+ def extract_mediafire_url
38
+ rendered_page.css('.download_link a').first['href']
39
+ end
40
+
41
+ def extract_dropbox_url
42
+ rendered_page.css('#default_content_download_button').first['href']
43
+ end
44
+
45
+ def extract_curseforge_url
46
+ rendered_html("#{url}/files/latest").strip
47
+ end
48
+
49
+ def extract_box_url
50
+ raw_html = HTTParty.get(url)
51
+
52
+ shared_name = url.split("/").last
53
+ file_id = raw_html.scan(/itemTypedID: \"(f_\d+)\"/)[0][0]
54
+
55
+ box_intermediate_url(shared_name, file_id)
56
+ end
57
+
58
+ def box_intermediate_url(shared_name, file_id)
59
+ base = "https://app.box.com/index.php?rm=box_download_shared_file"
60
+ shared_name_part = "&shared_name=#{shared_name}"
61
+ file_id_part = "&file_id=#{file_id}"
62
+
63
+ base + shared_name_part + file_id_part
64
+ end
65
+
66
+ def rendered_page(url = self.url)
67
+ Nokogiri::HTML(rendered_html(url))
68
+ end
69
+
70
+ def rendered_html(url)
71
+ Dir.chdir(File.dirname(__FILE__)) do
72
+ `phantomjs page_fetcher.js #{url}`
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,61 @@
1
+ require 'shellwords'
2
+
3
+ module Kosmos
4
+ module GitAdapter
5
+ class << self
6
+ def init_repo(path)
7
+ Dir.chdir(path) do
8
+ `git init`
9
+ end
10
+ end
11
+
12
+ def commit_everything(repo_path, commit_message)
13
+ Dir.chdir(repo_path) do
14
+ `git add -A -f`
15
+ `git commit --allow-empty -m #{commit_message.shellescape}`
16
+ end
17
+ end
18
+
19
+ def revert_commit(repo_path, commit, commit_message)
20
+ Dir.chdir(repo_path) do
21
+ `git revert --no-commit #{commit.sha}`
22
+ `git add -A -f`
23
+ `git commit --allow-empty -m #{commit_message.shellescape}`
24
+ end
25
+ end
26
+
27
+ def list_commits(repo_path)
28
+ Dir.chdir(repo_path) do
29
+ `git log --oneline`.lines.map do |line|
30
+ sha, message = line.split(' ', 2)
31
+ Commit.new(message, sha)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ class Commit < Struct.new(:message, :sha)
38
+ def pre?
39
+ type == :pre
40
+ end
41
+
42
+ def post?
43
+ type == :post
44
+ end
45
+
46
+ def uninstall?
47
+ type == :uninstall
48
+ end
49
+
50
+ def type
51
+ # "POST: Example" --> :post
52
+ message.split(':').first.downcase.to_sym
53
+ end
54
+
55
+ def subject
56
+ # "POST: Example\n" --> "Example"
57
+ message.split(' ', 2).last.strip
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,119 @@
1
+ require 'pathname'
2
+ require 'httparty'
3
+ require 'zip'
4
+ require 'tmpdir'
5
+
6
+ module Kosmos
7
+ class Package
8
+ include PackageDsl
9
+
10
+ attr_reader :ksp_path, :download_dir
11
+
12
+ [:title, :url].each do |param|
13
+ define_singleton_method(param) do |value = nil|
14
+ if value
15
+ instance_variable_set("@#{param}", value)
16
+ else
17
+ instance_variable_get("@#{param}")
18
+ end
19
+ end
20
+ end
21
+
22
+ # Internal version of the `install` method, which saves before actually
23
+ # performing the installation.
24
+ def install!(ksp_path)
25
+ @ksp_path = ksp_path
26
+ @download_dir = self.class.unzip!
27
+
28
+ Util.log "Saving your work before installing ..."
29
+ Versioner.mark_preinstall(ksp_path, self.class)
30
+
31
+ Util.log "Installing #{self.class.title} ..."
32
+ install
33
+
34
+ Util.log "Cleaning up ..."
35
+ Kosmos.config.post_processors.each { |p| p.post_process(ksp_path) }
36
+
37
+ Versioner.mark_postinstall(ksp_path, self.class)
38
+ end
39
+
40
+ class << self
41
+ def aliases(*aliases)
42
+ @aliases ||= []
43
+
44
+ if aliases.any?
45
+ @aliases = aliases
46
+ else
47
+ @aliases
48
+ end
49
+ end
50
+
51
+ # a callback for when a subclass of this class is created
52
+ def inherited(package)
53
+ (@@packages ||= []) << package
54
+ end
55
+
56
+ def normalize_for_find(name)
57
+ name.downcase.gsub(' ', "-")
58
+ end
59
+
60
+ def find(name)
61
+ @@packages.find do |package|
62
+ [package.title, package.aliases].flatten.any? do |candidate_name|
63
+ normalize_for_find(candidate_name) == normalize_for_find(name)
64
+ end
65
+ end
66
+ end
67
+
68
+ def unzip!
69
+ download_file = download!
70
+
71
+ Util.log "Unzipping ..."
72
+
73
+ output_path = Pathname.new(download_file.path).parent.to_s
74
+
75
+ Zip::File.open(download_file.path) do |zip_file|
76
+ zip_file.each do |entry|
77
+ destination = File.join(output_path, entry.name)
78
+ parent_dir = File.expand_path('..', destination)
79
+
80
+ FileUtils.mkdir_p(parent_dir) unless File.exists?(parent_dir)
81
+
82
+ entry.extract(destination)
83
+ end
84
+ end
85
+
86
+ File.delete(File.absolute_path(download_file))
87
+
88
+ output_path
89
+ end
90
+
91
+ def download!
92
+ Util.log "The package is found at #{url}. Finding the download URL ..."
93
+ download_url = DownloadUrl.new(url).resolve_download_url
94
+
95
+
96
+ Util.log "Found it. Downloading from #{download_url} ..."
97
+ downloaded_file = HTTParty.get(download_url)
98
+
99
+ tmpdir = Dir.mktmpdir
100
+
101
+ download_file = File.new(File.join(tmpdir, 'download'), 'w+')
102
+ download_file.write(downloaded_file)
103
+ download_file.close
104
+
105
+ download_file
106
+ end
107
+ end
108
+
109
+ # Now, let's include all the known packages.
110
+ Dir[File.join(File.dirname(__FILE__), 'packages', '*.rb')].each do |file|
111
+ require file
112
+ end
113
+
114
+ # ... and the post-processors too.
115
+ Dir[File.join(File.dirname(__FILE__), 'post_processors', '*.rb')].each do |file|
116
+ require file
117
+ end
118
+ end
119
+ end