nova 0.0.2

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 (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