nova 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +19 -0
  3. data/README.md +29 -0
  4. data/bin/nova +8 -0
  5. data/lib/generator/template/new_install/galaxy/some_star.rb +3 -0
  6. data/lib/generator/template/new_install/supernova.yml +16 -0
  7. data/lib/nova.rb +49 -0
  8. data/lib/nova/cli.rb +62 -0
  9. data/lib/nova/commands/server.rb +71 -0
  10. data/lib/nova/common.rb +17 -0
  11. data/lib/nova/common/event_handler.rb +165 -0
  12. data/lib/nova/common/event_handler/event.rb +147 -0
  13. data/lib/nova/common/features.rb +93 -0
  14. data/lib/nova/common/features/feature.rb +65 -0
  15. data/lib/nova/common/metadata.rb +65 -0
  16. data/lib/nova/common/metadata/data.rb +171 -0
  17. data/lib/nova/common/star_management.rb +164 -0
  18. data/lib/nova/constructor.rb +84 -0
  19. data/lib/nova/exceptions.rb +16 -0
  20. data/lib/nova/project.rb +199 -0
  21. data/lib/nova/remote.rb +10 -0
  22. data/lib/nova/remote/fake.rb +51 -0
  23. data/lib/nova/remote/fake/commands.rb +44 -0
  24. data/lib/nova/remote/fake/file_system.rb +76 -0
  25. data/lib/nova/remote/fake/operating_system.rb +52 -0
  26. data/lib/nova/remote/fake/platform.rb +89 -0
  27. data/lib/nova/star.rb +25 -0
  28. data/lib/nova/starbound.rb +14 -0
  29. data/lib/nova/starbound/client.rb +59 -0
  30. data/lib/nova/starbound/encryptor.rb +134 -0
  31. data/lib/nova/starbound/encryptors.rb +13 -0
  32. data/lib/nova/starbound/encryptors/openssl.rb +122 -0
  33. data/lib/nova/starbound/encryptors/plaintext.rb +64 -0
  34. data/lib/nova/starbound/encryptors/rbnacl.rb +67 -0
  35. data/lib/nova/starbound/protocol.rb +81 -0
  36. data/lib/nova/starbound/protocol/encryption.rb +48 -0
  37. data/lib/nova/starbound/protocol/exceptions.rb +38 -0
  38. data/lib/nova/starbound/protocol/messages.rb +116 -0
  39. data/lib/nova/starbound/protocol/packet.rb +267 -0
  40. data/lib/nova/starbound/protocol/socket.rb +231 -0
  41. data/lib/nova/starbound/server.rb +182 -0
  42. data/lib/nova/version.rb +5 -0
  43. data/spec/constructor_spec.rb +20 -0
  44. data/spec/local_spec.rb +26 -0
  45. data/spec/nova_spec.rb +7 -0
  46. data/spec/spec_helper.rb +19 -0
  47. data/spec/star/some_type.rb +27 -0
  48. data/spec/star_spec.rb +107 -0
  49. data/spec/starbound/encryptor_spec.rb +33 -0
  50. data/spec/starbound/openssl_encryptor_spec.rb +80 -0
  51. data/spec/starbound/packet_spec.rb +61 -0
  52. data/spec/starbound/plaintext_encryptor_spec.rb +27 -0
  53. data/spec/starbound/protocol_spec.rb +163 -0
  54. data/spec/starbound/rbnacl_encryptor_spec.rb +70 -0
  55. metadata +166 -0
@@ -0,0 +1,147 @@
1
+ module Nova
2
+ module Common
3
+ module EventHandler
4
+
5
+ # This represents an event that can be run. It may also represent
6
+ # an event that will be run, and is being used to match the events
7
+ # in the set.
8
+ # Basically, an event is defined when +:on+ is called on a Star,
9
+ # and an {Event} is created.
10
+ # It is added to an event list, which is a set. Later, when that
11
+ # class is instantized, and an event is ran, an {Event} is created
12
+ # and the set is searched for a match to that {Event}.
13
+ class Event
14
+
15
+ include Comparable
16
+
17
+ # The name of the event.
18
+ #
19
+ # @return [Symbol]
20
+ attr_reader :name
21
+
22
+ # The options defined at compile time for the event.
23
+ #
24
+ # @return [Hash]
25
+ attr_reader :options
26
+
27
+ # The block defined for the event. Should be able to accept one
28
+ # parameter, or less.
29
+ #
30
+ # @return [Proc]
31
+ attr_reader :block
32
+
33
+ # The type of {Event} this is. By default, this value is
34
+ # +:definition+, but when using this event to find another event,
35
+ # its value should be +:search+.
36
+ #
37
+ # @return [Symbol]
38
+ attr_accessor :type
39
+
40
+ # Initialize the event.
41
+ #
42
+ # @param name [Symbol] the name of the event to respond to.
43
+ # @param options [Hash] the options of the event.
44
+ # @param block [Proc] the defining block of the event.
45
+ # @option options [Symbol] :on the platform the event
46
+ # is written for. If this doesn't match the current
47
+ # platform, the event is never run. Must be in the
48
+ # results of {Remote::Fake::Platforms#platform} (or
49
+ # remote's definition of platform). Can also be +:for+.
50
+ # @option options [Symbol, Array<Symbol>] :requires
51
+ # what options the event requires when being run. The
52
+ # value will be matched against the keys of the hash
53
+ # passed, and if the hash doesn't contain all of the
54
+ # values, the event doesn't match. Can also be
55
+ # +:require+.
56
+ # @option options [Hash] :defaults the default values to be
57
+ # used when running the event. Merged into the given
58
+ # options such that the given options overwrite the
59
+ # defaults.
60
+ def initialize(name, options, block = nil)
61
+ @name = name
62
+ @options = options
63
+ @block = block
64
+ @type = :definition
65
+ end
66
+
67
+ # Compares this event to another event. If the argument isn't
68
+ # an {Event}, it is compared to the name of the event. If it
69
+ # is, the event's names and options are compared.
70
+ #
71
+ # @param other [Event, Object] the event to compare to.
72
+ # @return [Numeric] the comparison result.
73
+ def <=>(other)
74
+ return @name == other unless Event === other
75
+
76
+ (@name <=> other.name) + (@options <=> other.options)
77
+ end
78
+
79
+ # Runs the event, calling the block with the given options.
80
+ #
81
+ # @param context [Object] the context to run it in.
82
+ # @param options [Hash] the options.
83
+ # @return [Object, nil]
84
+ def run(context, options = {})
85
+ #@block.call(options)
86
+
87
+ if @options[:defaults]
88
+ options = @options[:defaults].merge(options)
89
+ end
90
+
91
+ context.instance_exec(options, &@block)
92
+ end
93
+
94
+ # Whether or not this event is a search event.
95
+ #
96
+ # @return [Boolean]
97
+ def search?
98
+ type == :search
99
+ end
100
+
101
+ # Whether or not this event matches another event, to see if it
102
+ # can be ran using this event definition.
103
+ #
104
+ # @param star [Class, #platform]
105
+ # @param event [Symbol]
106
+ # @return [Boolean]
107
+ def match?(star, event)
108
+ event.name == name &&
109
+ check_platform_requirement(star) && check_options_requirements(event.options)
110
+ end
111
+
112
+ private
113
+
114
+ # Checks the +:for+ option to see if it matches the current
115
+ # platform. If it's +nil+, or a false value, this returns true.
116
+ # If it's anything else, it'll try to compare it to the
117
+ # current platform, as returned by {Platforms#platform}.
118
+ #
119
+ # @api private
120
+ # @return [Boolean]
121
+ def check_platform_requirement(star)
122
+ if options[:for] || options[:on]
123
+ star.platform.include?(options[:for] || options[:on])
124
+ else
125
+ true
126
+ end
127
+ end
128
+
129
+ # Checks the given runtime options for required options. If no
130
+ # required options exist, returns true. Otherwise, checks the
131
+ # keys of the runtime options to see if they contain all of the
132
+ # required options.
133
+ #
134
+ # @api private
135
+ # @return [Boolean]
136
+ def check_options_requirements(runtime_options)
137
+ required_options = options[:requires] || options[:require]
138
+ return true unless required_options
139
+
140
+ ([required_options].flatten - runtime_options.keys).size == 0
141
+ end
142
+
143
+
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,93 @@
1
+ require 'forwardable'
2
+
3
+ require 'nova/common/features/feature'
4
+
5
+ module Nova
6
+ module Common
7
+
8
+ # The features that the star has. These are optional
9
+ # behaviors that are defined on the stars, but if they are
10
+ # implemented they should follow around the same behaviours of
11
+ # other features implemented on other stars with the same name.
12
+ module Features
13
+
14
+ # Class methods.
15
+ module ClassMethods
16
+
17
+ # The list of features the star supports.
18
+ #
19
+ # @return [Hash] the features.
20
+ def features
21
+ @features ||= {}
22
+ end
23
+
24
+ # Whether or not this star supports a feature.
25
+ #
26
+ # @return [Boolean]
27
+ def supports?(feature_name)
28
+ features.key? feature_name
29
+ end
30
+
31
+ # Define a feature, with the given name and block.
32
+ #
33
+ # @param name [Symbol] the name of the feature.
34
+ # @param options [Hash] the options for the feature.
35
+ # @yield to create the feature.
36
+ # @return [Feature] the feature that was defined.
37
+ def feature(name, options = {}, &block)
38
+ new_feature = Feature.new(name, options)
39
+ new_feature.instance_exec &block
40
+ features[name] = new_feature
41
+ end
42
+
43
+ end
44
+
45
+ # Instance methods.
46
+ module InstanceMethods
47
+
48
+ extend Forwardable
49
+
50
+ # A hash of features. Any features are bound to this class,
51
+ # after their first access. If a feature is accessed without
52
+ # existing, a fake feature is created and bound to self.
53
+ # All features are cached in the hash after being bound.
54
+ #
55
+ # @see Features::ClassMethods#features
56
+ # @return [Hash]
57
+ def features
58
+ @_features ||= Hash.new do |hash, key|
59
+ class_feature = self.class.features[key]
60
+
61
+ if class_feature
62
+ hash[key] = class_feature.bind(self)
63
+ else
64
+ hash[key] = Feature.new(key, {}).bind(self).fake!
65
+ end
66
+ end
67
+ end
68
+
69
+ # Returns a feature that matches the given name. If it
70
+ # doesn't exist, a fake one is created, and bound to self.
71
+ #
72
+ # @param name [Symbol] the name of the feature.
73
+ # @return [Feature]
74
+ def feature(name)
75
+ features[name]
76
+ end
77
+
78
+ def_delegators "self.class", :supports?
79
+ end
80
+
81
+ # Called when {Features} is included. Extends what included
82
+ # it by {ClassMethods}, and includes {InstanceMethods}.
83
+ #
84
+ # @param receiver [Object]
85
+ # @return [void]
86
+ # @api private
87
+ def self.included(receiver)
88
+ receiver.extend ClassMethods
89
+ receiver.send :include, InstanceMethods
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,65 @@
1
+ module Nova
2
+ module Common
3
+ module Features
4
+
5
+ # The information about the feature that was defined.
6
+ class Feature
7
+
8
+ # The name of the feature.
9
+ #
10
+ # @return [Symbol]
11
+ attr_accessor :name
12
+
13
+ # The options of the feature.
14
+ #
15
+ # @return [Hash]
16
+ attr_accessor :options
17
+
18
+ def initialize(name, options)
19
+ @name = name
20
+ @options = options
21
+ @bind = Object.new
22
+ @fake = false
23
+ end
24
+
25
+ include EventHandler
26
+
27
+ # Enables the feature and runs the :enable event, if it
28
+ # exists.
29
+ #
30
+ # @return [nil, Object]
31
+ def enable!
32
+ run(:enable)
33
+ end
34
+
35
+ # Disables the feature and runs the :disable event, if it
36
+ # exists.
37
+ #
38
+ # @return [nil, Object]
39
+ def disable!
40
+ run(:disable)
41
+ end
42
+
43
+ # Whether or not this feature is fake. By fake, it means that
44
+ # it was not created with the defining class as a feature; it
45
+ # does not have any events at all, and its only purpose is to
46
+ # mock the behavior of a real, defined feature.
47
+ #
48
+ # @return [Boolean]
49
+ def fake?
50
+ @fake
51
+ end
52
+
53
+ # Marks this feature as fake. This is not reversable.
54
+ #
55
+ # @see #fake?
56
+ # @return [self]
57
+ def fake!
58
+ @fake = true
59
+ self
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ require 'nova/common/metadata/data'
2
+
3
+ module Nova
4
+ module Common
5
+
6
+ # Manages the metadata, such as required options, ruby versions,
7
+ # required platforms/versions, etc.
8
+ module Metadata
9
+
10
+ # Class methods.
11
+ module ClassMethods
12
+
13
+ # @overload metadata(&block)
14
+ # Runs the metadata block in a metadata instance, and then
15
+ # sets the metadata information for this star.
16
+ #
17
+ # @yield [Data]
18
+ # @return [Data]
19
+ # @overload metadata
20
+ # Returns the metadata for this star.
21
+ #
22
+ # @return [Data]
23
+ def metadata(&block)
24
+ if block_given?
25
+ data = Data.new
26
+ data.instance_exec data, &block
27
+ @metadata = data
28
+ else
29
+ @metadata ||= Data.new
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ # Instance methods.
36
+ module InstanceMethods
37
+
38
+ # Handles validation for the metadata.
39
+ def initialize(*)
40
+ @meta = self.class.metadata
41
+ @meta.validate! remote
42
+ end
43
+
44
+ # Sets the options, validating them.
45
+ def options=(options)
46
+ @meta.validate_options! options
47
+ @options = options
48
+ end
49
+
50
+ end
51
+
52
+ # Called when {Metadata} is included. Extends what included
53
+ # it by {ClassMethods}, and includes {InstanceMethods}.
54
+ #
55
+ # @param receiver [Object]
56
+ # @return [void]
57
+ # @api private
58
+ def self.included(receiver)
59
+ receiver.extend ClassMethods
60
+ receiver.send :include, InstanceMethods
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,171 @@
1
+ module Nova
2
+ module Common
3
+ module Metadata
4
+
5
+ # The data from the definition of the metadata in the star.
6
+ # This is what the block is run in an instance of.
7
+ class Data
8
+
9
+ # The data contained in this class.
10
+ #
11
+ # @return [Hash<Symbol, Object>]
12
+ attr_reader :data
13
+
14
+ # Initialize the data class.
15
+ def initialize
16
+ @data = {
17
+ :rubys => [],
18
+ :platforms => [],
19
+ :stars => [],
20
+ :required_options => [],
21
+ :version => Gem::Version.new("0.0.0") }
22
+ end
23
+
24
+ # @!method requires_platform(name, *versions)
25
+ # The platform version requirement. Each call to this
26
+ # method adds a platform that can be used, and the
27
+ # versions that are required for that platform. +:all+
28
+ # represents all platforms.
29
+ #
30
+ # @see Gem::Requirement
31
+ # @param name [Symbol] the name of the platform.
32
+ # @param versions [String] the versions of that platform
33
+ # this star is compatible with.
34
+ # @return [void]
35
+ # @!method requires_ruby(name, *versions)
36
+ # The ruby version requirement. Each call to this method
37
+ # adds a platform that can be used, and the versions that
38
+ # are required for that platform. +:all+ represents all
39
+ # platforms.
40
+ #
41
+ # @see Gem::Requirement
42
+ # @param name [Symbol] the name of the platform, such as
43
+ # +:jruby+ or +:mri+.
44
+ # @param versions [String] the versions of that platform
45
+ # that this star is compatible with.
46
+ # @!method requires_star(name, *versions)
47
+ # Requires stars. Uses the given name as the star name.
48
+ #
49
+ # @see Gem::Requirement
50
+ # @param name [Symbol] the name of the star.
51
+ # @param versions [String] the versions of that star that
52
+ # are compatible with this star.
53
+ #
54
+ # @!parse alias_method :require_ruby, :requires_ruby
55
+ # @!parse alias_method :requires_rubys, :requires_ruby
56
+ # @!parse alias_method :require_rubys, :requires_ruby
57
+ # @!parse alias_method :require_platform, :requires_platform
58
+ # @!parse alias_method :requires_platforms, :requires_platform
59
+ # @!parse alias_method :require_platforms, :requires_platform
60
+ # @!parse alias_method :require_star, :requires_star
61
+ # @!parse alias_method :requires_stars, :requires_star
62
+ # @!parse alias_method :require_stars, :requires_star
63
+ [:ruby, :platform, :star].each do |type|
64
+ define_method(:"requires_#{type}") do |p, *versions|
65
+ data[:"#{type}s"].push(:name => p, :version =>
66
+ Gem::Requirement.new(*[versions].flatten))
67
+ end
68
+
69
+ alias_method :"require_#{type}", :"requires_#{type}"
70
+ alias_method :"requires_#{type}s", :"requires_#{type}"
71
+ alias_method :"require_#{type}s", :"requires_#{type}"
72
+ end
73
+
74
+ # The options that are required by this star.
75
+ #
76
+ # @param options [Symbol] the option that is required.
77
+ # @return [void]
78
+ def requires_option(*options)
79
+ data[:required_options].push(*[options].flatten)
80
+ end
81
+
82
+ alias_method :requires_options, :requires_option
83
+ alias_method :require_option, :requires_option
84
+ alias_method :require_options, :requires_options
85
+
86
+ # Sets the version of the current star.
87
+ #
88
+ # @see Gem::Version
89
+ # @param version [String] the version of the star.
90
+ # @return [void]
91
+ def version=(version)
92
+ data[:version] = Gem::Version.new(version)
93
+ end
94
+
95
+ # Validates the current platform, to make sure that the
96
+ # running ruby version and the platform name and version
97
+ # match those required by this star.
98
+ #
99
+ # @return [void]
100
+ def validate!(remote)
101
+ check_against :ruby do |ruby|
102
+ if [:all, :any].include? ruby[:name]
103
+ ruby[:version].satisfied_by?(
104
+ Gem::Version.new(RUBY_VERSION))
105
+ else
106
+ ruby[:name] == RUBY_ENGINE.downcase.intern &&
107
+ ruby[:version] == ruby_version
108
+ end
109
+ end
110
+
111
+ version = Gem::Version.new remote.platform.version || "0.0.0"
112
+
113
+ check_against :platform do |platform|
114
+ remote.platforms.include?(platform[:name]) &&
115
+ platform[:version] == version
116
+ end
117
+ end
118
+
119
+ # Validates the given options, making sure that the options
120
+ # contain the required options for the star.
121
+ #
122
+ # @return [void]
123
+ def validate_options!(options)
124
+ keys = options.keys
125
+
126
+ unless (data[:required_options] - keys).empty?
127
+ raise InvalidOptionsError, "Missing options " +
128
+ "#{(data[:required_options] - keys).join(', ')}"
129
+ end
130
+ end
131
+
132
+ private
133
+
134
+ # Checks the given type against the block. Injects the
135
+ # type's array with false, and calls the block, trying to
136
+ # see if any element in the type's array makes the block
137
+ # return true. If none of them do, it raises an error,
138
+ # unless there's no element in the type's array.
139
+ #
140
+ # @param what [Symbol] the type. Normally +:ruby+ or
141
+ # +:platform+.
142
+ # @yield [Hash] the object to check.
143
+ # @raise [NoPlatformError] if none of the yields give true.
144
+ # @return [void]
145
+ def check_against(what, &block)
146
+ result = data[:"#{what}s"].inject(false) do |v, obj|
147
+ v || block.call(obj)
148
+ end
149
+
150
+ unless result || data[:"#{what}s"].empty?
151
+ raise NoPlatformError, "Could not match any version " +
152
+ "of #{what}s."
153
+ end
154
+ end
155
+
156
+ # Returns the most relevant ruby version there is.
157
+ #
158
+ # @return [Gem::Version]
159
+ def ruby_version
160
+ Gem::Version.new case RUBY_ENGINE
161
+ when "jruby"
162
+ JRUBY_VERSION
163
+ else
164
+ RUBY_VERSION
165
+ end
166
+ end
167
+
168
+ end
169
+ end
170
+ end
171
+ end