kosmos 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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