rubycut-babushka 0.10.6

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 (171) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +31 -0
  3. data/README.markdown +246 -0
  4. data/Rakefile +26 -0
  5. data/bin/babushka +11 -0
  6. data/deps/babushka.rb +101 -0
  7. data/deps/dev.rb +12 -0
  8. data/deps/fhs.rb +31 -0
  9. data/deps/git.rb +29 -0
  10. data/deps/homebrew.rb +30 -0
  11. data/deps/os_x.rb +33 -0
  12. data/deps/packages.rb +22 -0
  13. data/deps/pkg_managers.rb +110 -0
  14. data/deps/ruby.rb +23 -0
  15. data/deps/rubygems.rb +24 -0
  16. data/deps/system.rb +10 -0
  17. data/deps/templates/app.rb +68 -0
  18. data/deps/templates/external.rb +12 -0
  19. data/deps/templates/installer.rb +31 -0
  20. data/deps/templates/managed.rb +105 -0
  21. data/deps/templates/ppa.rb +24 -0
  22. data/deps/templates/src.rb +42 -0
  23. data/deps/templates/tmbundle.rb +15 -0
  24. data/lib/babushka.rb +28 -0
  25. data/lib/babushka/accepts_block_for.rb +72 -0
  26. data/lib/babushka/accepts_list_for.rb +49 -0
  27. data/lib/babushka/accepts_value_for.rb +24 -0
  28. data/lib/babushka/base.rb +78 -0
  29. data/lib/babushka/bug_reporter.rb +55 -0
  30. data/lib/babushka/cmdline.rb +133 -0
  31. data/lib/babushka/cmdline/handler.rb +41 -0
  32. data/lib/babushka/cmdline/helpers.rb +127 -0
  33. data/lib/babushka/cmdline/parser.rb +69 -0
  34. data/lib/babushka/colorizer.rb +59 -0
  35. data/lib/babushka/core_patches/array.rb +171 -0
  36. data/lib/babushka/core_patches/blank.rb +22 -0
  37. data/lib/babushka/core_patches/bytes.rb +52 -0
  38. data/lib/babushka/core_patches/hash.rb +107 -0
  39. data/lib/babushka/core_patches/hashish.rb +14 -0
  40. data/lib/babushka/core_patches/integer.rb +25 -0
  41. data/lib/babushka/core_patches/io.rb +8 -0
  42. data/lib/babushka/core_patches/numeric.rb +16 -0
  43. data/lib/babushka/core_patches/object.rb +27 -0
  44. data/lib/babushka/core_patches/string.rb +116 -0
  45. data/lib/babushka/core_patches/symbol.rb +12 -0
  46. data/lib/babushka/core_patches/try.rb +15 -0
  47. data/lib/babushka/core_patches/uri.rb +24 -0
  48. data/lib/babushka/dep.rb +470 -0
  49. data/lib/babushka/dep_context.rb +18 -0
  50. data/lib/babushka/dep_definer.rb +115 -0
  51. data/lib/babushka/dep_pool.rb +49 -0
  52. data/lib/babushka/dep_runner.rb +85 -0
  53. data/lib/babushka/dsl.rb +26 -0
  54. data/lib/babushka/git_repo.rb +185 -0
  55. data/lib/babushka/helpers/git_helpers.rb +32 -0
  56. data/lib/babushka/helpers/log_helpers.rb +176 -0
  57. data/lib/babushka/helpers/path_helpers.rb +34 -0
  58. data/lib/babushka/helpers/run_helpers.rb +145 -0
  59. data/lib/babushka/helpers/shell_helpers.rb +229 -0
  60. data/lib/babushka/helpers/suggest_helpers.rb +16 -0
  61. data/lib/babushka/helpers/uri_helpers.rb +36 -0
  62. data/lib/babushka/ip.rb +160 -0
  63. data/lib/babushka/lambda_chooser.rb +40 -0
  64. data/lib/babushka/levenshtein.rb +125 -0
  65. data/lib/babushka/meta_dep.rb +65 -0
  66. data/lib/babushka/meta_dep_context.rb +15 -0
  67. data/lib/babushka/parameter.rb +143 -0
  68. data/lib/babushka/pkg_helper.rb +81 -0
  69. data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
  70. data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
  71. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
  72. data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
  73. data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
  74. data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
  75. data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
  76. data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
  77. data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
  78. data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
  79. data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
  80. data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
  81. data/lib/babushka/popen.rb +40 -0
  82. data/lib/babushka/prompt.rb +176 -0
  83. data/lib/babushka/renderable.rb +67 -0
  84. data/lib/babushka/resource.rb +215 -0
  85. data/lib/babushka/run_reporter.rb +60 -0
  86. data/lib/babushka/shell.rb +108 -0
  87. data/lib/babushka/source.rb +216 -0
  88. data/lib/babushka/source_pool.rb +146 -0
  89. data/lib/babushka/system_definitions.rb +97 -0
  90. data/lib/babushka/system_profile.rb +210 -0
  91. data/lib/babushka/task.rb +142 -0
  92. data/lib/babushka/vars.rb +108 -0
  93. data/lib/babushka/version_of.rb +65 -0
  94. data/lib/babushka/version_str.rb +57 -0
  95. data/lib/babushka/xml_string.rb +28 -0
  96. data/lib/components.rb +82 -0
  97. data/lib/fancypath/fancypath.rb +200 -0
  98. data/lib/inkan/inkan.rb +76 -0
  99. data/spec/acceptance/acceptance.rb +43 -0
  100. data/spec/acceptance_helper.rb +113 -0
  101. data/spec/archives/Blah.app.zip +0 -0
  102. data/spec/archives/archive.tar +0 -0
  103. data/spec/archives/archive.tar.bz2 +0 -0
  104. data/spec/archives/archive.tar.gz +0 -0
  105. data/spec/archives/archive.tbz2 +0 -0
  106. data/spec/archives/archive.tgz +0 -0
  107. data/spec/archives/archive.zip +0 -0
  108. data/spec/archives/content.txt +5 -0
  109. data/spec/archives/invalid_archive +5 -0
  110. data/spec/archives/nested archive/content.txt +5 -0
  111. data/spec/archives/nested_archive.tar +0 -0
  112. data/spec/archives/really_a_gzip.zip +0 -0
  113. data/spec/archives/test-0.3.1.tgz +0 -0
  114. data/spec/archives/tgz_archive +0 -0
  115. data/spec/archives/zip_without_extension +0 -0
  116. data/spec/babushka/accepts_for_spec.rb +174 -0
  117. data/spec/babushka/accepts_for_support.rb +72 -0
  118. data/spec/babushka/cmdline/console_spec.rb +11 -0
  119. data/spec/babushka/cmdline/help_spec.rb +61 -0
  120. data/spec/babushka/cmdline/version_spec.rb +10 -0
  121. data/spec/babushka/core_patches_spec.rb +171 -0
  122. data/spec/babushka/dep_context_spec.rb +58 -0
  123. data/spec/babushka/dep_definer_spec.rb +152 -0
  124. data/spec/babushka/dep_definer_support.rb +36 -0
  125. data/spec/babushka/dep_spec.rb +567 -0
  126. data/spec/babushka/dep_support.rb +29 -0
  127. data/spec/babushka/deps_spec.rb +113 -0
  128. data/spec/babushka/gem_helper_spec.rb +90 -0
  129. data/spec/babushka/git_repo_spec.rb +396 -0
  130. data/spec/babushka/ip_spec.rb +131 -0
  131. data/spec/babushka/lambda_chooser_spec.rb +115 -0
  132. data/spec/babushka/meta_dep_definer_spec.rb +127 -0
  133. data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
  134. data/spec/babushka/parameter_spec.rb +135 -0
  135. data/spec/babushka/path_helpers_spec.rb +102 -0
  136. data/spec/babushka/prompt_spec.rb +188 -0
  137. data/spec/babushka/renderable_spec.rb +100 -0
  138. data/spec/babushka/resource_spec.rb +141 -0
  139. data/spec/babushka/run_helpers_spec.rb +26 -0
  140. data/spec/babushka/shell_helpers_spec.rb +244 -0
  141. data/spec/babushka/shell_spec.rb +19 -0
  142. data/spec/babushka/source_pool_spec.rb +320 -0
  143. data/spec/babushka/source_pool_support.rb +31 -0
  144. data/spec/babushka/source_spec.rb +382 -0
  145. data/spec/babushka/source_support.rb +17 -0
  146. data/spec/babushka/system_profile_spec.rb +61 -0
  147. data/spec/babushka/task_spec.rb +141 -0
  148. data/spec/babushka/uri_spec.rb +13 -0
  149. data/spec/babushka/vars_spec.rb +59 -0
  150. data/spec/babushka/version_of_spec.rb +110 -0
  151. data/spec/babushka/version_str_spec.rb +130 -0
  152. data/spec/babushka/version_str_support.rb +37 -0
  153. data/spec/babushka/xml_string_spec.rb +98 -0
  154. data/spec/deps/bad/broken.rb +7 -0
  155. data/spec/deps/bad/working.rb +3 -0
  156. data/spec/deps/good/meta.rb +14 -0
  157. data/spec/deps/good/test.rb +11 -0
  158. data/spec/deps/outer/deps.rb +19 -0
  159. data/spec/deps/outer/more deps.rb +11 -0
  160. data/spec/deps/params/params.rb +10 -0
  161. data/spec/fancypath/fancypath_spec.rb +272 -0
  162. data/spec/fancypath_support.rb +10 -0
  163. data/spec/inkan/inkan_spec.rb +217 -0
  164. data/spec/renderable/different_example.conf.erb +4 -0
  165. data/spec/renderable/example.conf.erb +3 -0
  166. data/spec/renderable/example.sh +6 -0
  167. data/spec/renderable/with_binding.conf.erb +4 -0
  168. data/spec/renderable/xml_example.conf.erb +8 -0
  169. data/spec/repos/remote.git.tgz +0 -0
  170. data/spec/spec_helper.rb +87 -0
  171. metadata +238 -0
@@ -0,0 +1,216 @@
1
+ module Babushka
2
+ class SourceError < StandardError
3
+ end
4
+ class Source
5
+ include GitHelpers
6
+ include LogHelpers
7
+ extend LogHelpers
8
+ extend ShellHelpers
9
+ include PathHelpers
10
+ extend PathHelpers
11
+
12
+ attr_reader :name, :uri, :deps, :templates
13
+
14
+ def self.present
15
+ source_prefix.glob('*').map(&:p).select {|path|
16
+ path.directory?
17
+ }.map {|path|
18
+ Source.for_path path
19
+ }.select {|source|
20
+ source.present?
21
+ }
22
+ end
23
+
24
+ def self.for_path path
25
+ remote = cd(path) { shell "git config remote.origin.url" }
26
+ if remote.nil?
27
+ Source.new path # local source
28
+ else
29
+ Source.new remote, :name => path.basename # remote source with custom path
30
+ end
31
+ end
32
+
33
+ def self.for_remote name
34
+ Source.new(default_remote_for(name), :name => name)
35
+ end
36
+
37
+ def self.default_remote_for name
38
+ "git://github.com/#{name}/babushka-deps.git"
39
+ end
40
+
41
+ require 'uri'
42
+ def self.discover_uri_and_type path
43
+ if path.nil?
44
+ [nil, :implicit]
45
+ elsif path.to_s[/^(git|http|file):\/\//]
46
+ [path.to_s, :public]
47
+ elsif path.to_s[/^(\w+@)?[a-zA-Z0-9.\-]+:/]
48
+ [path.to_s, :private]
49
+ else
50
+ [path.p, :local]
51
+ end
52
+ end
53
+
54
+ def self.default_name_for_uri uri
55
+ if uri.nil?
56
+ nil
57
+ else
58
+ File.basename(uri.to_s).chomp('.git')
59
+ end
60
+ end
61
+
62
+ def initialize path, opts = {}
63
+ raise ArgumentError, "Source.new options must be passed as a hash, not as #{opts.inspect}." unless opts.is_a?(Hash)
64
+ @uri, @type = self.class.discover_uri_and_type(path)
65
+ @name = (opts[:name] || self.class.default_name_for_uri(@uri)).to_s
66
+ @deps = DepPool.new self
67
+ @templates = DepPool.new self
68
+ @loaded = @currently_loading = false
69
+ end
70
+
71
+ def uri_matches? path
72
+ self.class.discover_uri_and_type(path).first == uri
73
+ end
74
+
75
+ def find dep_spec
76
+ load!
77
+ deps.for(dep_spec)
78
+ end
79
+
80
+ def find_template template_spec
81
+ load!
82
+ templates.for(template_spec)
83
+ end
84
+
85
+ def prefix
86
+ self.class.source_prefix
87
+ end
88
+ def path
89
+ if implicit? || local?
90
+ @uri
91
+ else
92
+ prefix / name
93
+ end
94
+ end
95
+
96
+ def repo
97
+ @repo ||= GitRepo.new(path) if cloneable?
98
+ end
99
+
100
+ def updated_at
101
+ Time.now - File.mtime(path)
102
+ end
103
+ def description_pieces
104
+ [
105
+ name,
106
+ uri.to_s,
107
+ type,
108
+ ("#{updated_at.round.xsecs} ago" if cloneable?)
109
+ ]
110
+ end
111
+ def type
112
+ @type
113
+ end
114
+ def cloneable?
115
+ [:public, :private].include? type
116
+ end
117
+ def cloned?
118
+ File.directory? path / '.git'
119
+ end
120
+ def present?
121
+ cloneable? ? cloned? : path.exists?
122
+ end
123
+ def local?
124
+ type == :local
125
+ end
126
+ def implicit?
127
+ type == :implicit
128
+ end
129
+
130
+ def == other
131
+ [:name, :uri, :type].all? {|method_name| other.respond_to? method_name } &&
132
+ name == other.name &&
133
+ uri == other.uri &&
134
+ type == other.type
135
+ end
136
+
137
+ def add!
138
+ if !cloneable?
139
+ log "Nothing to add for #{name}."
140
+ else
141
+ raise_unless_addable!
142
+ log_block "Adding #{name} from #{uri}" do
143
+ update!
144
+ end
145
+ end
146
+ end
147
+
148
+ def load!
149
+ unless @currently_loading
150
+ @currently_loading = true
151
+ update! if cloneable?
152
+ load_deps! unless implicit? # implicit sources can't be loaded.
153
+ @currently_loading = false
154
+ end
155
+ end
156
+
157
+ def load_deps!
158
+ unless @loaded
159
+ path.p.glob('**/*.rb').each {|f|
160
+ Base.sources.load_context :source => self, :path => f do
161
+ begin
162
+ load f
163
+ rescue Exception => e
164
+ log_error "#{e.backtrace.first}: #{e.message}"
165
+ log "Check #{(e.backtrace.detect {|l| l[f] } || f).sub(/\:in [^:]+$/, '')}."
166
+ debug e.backtrace * "\n"
167
+ end
168
+ end
169
+ }
170
+ debug "Loaded #{deps.count} deps from #{path}." unless deps.count.zero?
171
+ @loaded = true
172
+ end
173
+ end
174
+
175
+ def update!
176
+ if @updated
177
+ debug "Already pulled #{name} (#{uri}) this session."
178
+ true
179
+ elsif @updated == false
180
+ debug "Not updating #{name} (#{uri}) - it's offline."
181
+ elsif Base.sources.local_only?
182
+ debug "Not pulling #{name} (#{uri}) - in local-only mode."
183
+ true
184
+ elsif repo.exists? && repo.dirty?
185
+ log "Not updating #{name} (#{path}) because there are local changes."
186
+ elsif repo.exists? && repo.ahead?
187
+ log "Not updating #{name} (#{path}) because it's ahead of origin."
188
+ else
189
+ git(uri, :to => path, :log => true).tap {|result|
190
+ log "Marking #{uri} as offline for this run." unless result
191
+ @updated = result || false
192
+ }
193
+ end
194
+ end
195
+
196
+ private
197
+
198
+ def raise_unless_addable!
199
+ present_sources = Base.sources.all_present
200
+ uri_dup_source = present_sources.detect {|s| s.uri == uri && s.name != name }
201
+ name_dup_source = present_sources.detect {|s| s.name == name && s.uri != uri }
202
+ raise SourceError, "There is already a source called '#{name_dup_source.name}' (it contains #{name_dup_source.uri})." unless name_dup_source.nil?
203
+ raise SourceError, "The source #{uri_dup_source.uri} is already present (as '#{uri_dup_source.name}')." unless uri_dup_source.nil?
204
+ end
205
+
206
+ def self.source_prefix
207
+ SourcePrefix.p
208
+ end
209
+
210
+ public
211
+
212
+ def inspect
213
+ "#<Source:#{object_id} '#{name}' (#{deps.count} dep#{'s' unless deps.count == 1})>"
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,146 @@
1
+ module Babushka
2
+ class SourcePool
3
+ include Singleton
4
+
5
+ include LogHelpers
6
+
7
+ SEPARATOR = ':'
8
+
9
+ def current
10
+ @_cached_current ||= default.concat(standard)
11
+ @_cached_current.dup
12
+ end
13
+
14
+ def default
15
+ [anonymous, core].dup
16
+ end
17
+
18
+ def current_names
19
+ current.map {|source| source.deps.names }.flatten.uniq
20
+ end
21
+
22
+ def all_present
23
+ current.concat(Source.present)
24
+ end
25
+
26
+ def anonymous
27
+ @_cached_anonymous ||= Source.new(nil, :name => 'anonymous')
28
+ end
29
+ def core
30
+ @_cached_core ||= Source.new(Path.path / 'deps', :name => 'core')
31
+ end
32
+ def current_dir
33
+ @_cached_current_dir ||= Source.new('./babushka-deps', :name => 'current dir')
34
+ end
35
+ def personal
36
+ @_cached_personal ||= Source.new('~/.babushka/deps', :name => 'personal')
37
+ end
38
+
39
+ def standard
40
+ [current_dir, personal]
41
+ end
42
+
43
+ def source_for name
44
+ all_present.detect {|source| source.name == name } || Source.for_remote(name)
45
+ end
46
+
47
+ def dep_for dep_spec, opts = {}
48
+ if dep_spec.is_a?(Dep)
49
+ dep_spec
50
+ elsif dep_spec[/#{SEPARATOR}/] # If a source was specified, that's where we load from.
51
+ source_name, dep_name = dep_spec.split(SEPARATOR, 2)
52
+ source_for(source_name).find(dep_name)
53
+ elsif opts[:from]
54
+ opts[:from].find(dep_spec) || dep_for(dep_spec)
55
+ else # Otherwise, load from the current source (opts[:from]) or the standard set.
56
+ matches = Base.sources.current.map {|source| source.find(dep_spec) }.flatten.compact
57
+ if matches.length > 1
58
+ log "Multiple sources (#{matches.map(&:dep_source).map(&:name).join(',')}) contain a dep called '#{dep_spec}'."
59
+ else
60
+ matches.first
61
+ end
62
+ end
63
+ end
64
+
65
+ def template_for template_spec, opts = {}
66
+ if template_spec.nil?
67
+ nil
68
+ elsif template_spec[/#{SEPARATOR}/] # If a source was specified, that's where we load from.
69
+ source_name, template_name = template_spec.split(SEPARATOR, 2)
70
+ source_for(source_name).find_template(template_name)
71
+ elsif opts[:from]
72
+ opts[:from].find_template(template_spec) || template_for(template_spec)
73
+ else
74
+ matches = Base.sources.default.map {|source| source.find_template(template_spec) }.flatten.compact
75
+ if matches.length > 1
76
+ log "Multiple sources (#{matches.map(&:source).map(&:name).join(',')}) contain a template called '#{template_name}'."
77
+ else
78
+ matches.first
79
+ end
80
+ end
81
+ end
82
+
83
+ def update!
84
+ all_present.select {|source|
85
+ source.cloneable?
86
+ }.tap {|sources|
87
+ log "Updating #{sources.length} source#{'s' unless sources.length == 1}."
88
+ }.map {|source|
89
+ source.update!
90
+ }.all?
91
+ end
92
+
93
+ def list!
94
+ Logging.log_table(
95
+ ['Name', 'Source path', 'Type', 'Last updated'],
96
+ Source.present.tap {|sources|
97
+ log "There #{sources.length == 1 ? 'is' : 'are'} #{sources.length} source#{'s' unless sources.length == 1} in #{Source.source_prefix}:"
98
+ log ''
99
+ }.map(&:description_pieces)
100
+ )
101
+ end
102
+
103
+ def uncache!
104
+ current.each {|source| source.deps.uncache! }
105
+ end
106
+
107
+ def local_only?
108
+ @local_only
109
+ end
110
+
111
+ def local_only &block
112
+ previously = @local_only
113
+ @local_only = true
114
+ yield
115
+ ensure
116
+ @local_only = previously
117
+ end
118
+
119
+ def load_context context, &block
120
+ (@load_contexts ||= []).push context
121
+ yield
122
+ ensure
123
+ @load_contexts.pop
124
+ end
125
+
126
+ def current_real_load_source
127
+ current_load_context[:source]
128
+ end
129
+ def current_load_source
130
+ current_real_load_source || Base.sources.anonymous
131
+ end
132
+ def current_load_path
133
+ current_load_context[:path].try(:p)
134
+ end
135
+ def current_load_opts
136
+ current_load_context[:opts] || {}
137
+ end
138
+
139
+ private
140
+
141
+ def current_load_context
142
+ (@load_contexts ||= []).last || {}
143
+ end
144
+
145
+ end
146
+ end
@@ -0,0 +1,97 @@
1
+ module Babushka
2
+ class SystemDefinitions
3
+ def self.all_systems
4
+ names.keys
5
+ end
6
+ def self.all_flavours
7
+ names.values.map(&:keys).flatten
8
+ end
9
+ def self.all_names
10
+ names.values.map(&:values).map {|s| s.map(&:values) }.flatten
11
+ end
12
+ def self.all_tokens
13
+ all_systems + PkgHelper.all_manager_keys + all_flavours + all_names
14
+ end
15
+
16
+ def self.names
17
+ {
18
+ :osx => {
19
+ :osx => {
20
+ '10.3' => :panther,
21
+ '10.4' => :tiger,
22
+ '10.5' => :leopard,
23
+ '10.6' => :snow_leopard,
24
+ '10.7' => :lion
25
+ }
26
+ },
27
+ :linux => {
28
+ :ubuntu => {
29
+ '4.10' => :warty,
30
+ '5.04' => :hoary,
31
+ '5.10' => :breezy,
32
+ '6.06' => :dapper,
33
+ '6.10' => :edgy,
34
+ '7.04' => :feisty,
35
+ '7.10' => :gutsy,
36
+ '8.04' => :hardy,
37
+ '8.10' => :intrepid,
38
+ '9.04' => :jaunty,
39
+ '9.10' => :karmic,
40
+ '10.04' => :lucid,
41
+ '10.10' => :maverick,
42
+ '11.04' => :natty
43
+ },
44
+ :debian => {
45
+ '4.0' => :etch,
46
+ '5.0' => :lenny,
47
+ '6.0' => :squeeze,
48
+ '7.0' => :wheezy
49
+ }
50
+ },
51
+ :bsd => {
52
+ :dragonfly => {},
53
+ :freebsd => {}
54
+ }
55
+ }
56
+ end
57
+
58
+ def self.descriptions
59
+ {
60
+ :osx => {
61
+ :osx => {
62
+ '10.3' => 'Panther',
63
+ '10.4' => 'Tiger',
64
+ '10.5' => 'Leopard',
65
+ '10.6' => 'Snow Leopard',
66
+ '10.7' => 'Lion'
67
+ }
68
+ },
69
+ :linux => {
70
+ :ubuntu => {
71
+ '4.10' => 'Warty Warthog',
72
+ '5.04' => 'Hoary Hedgehog',
73
+ '5.10' => 'Breezy Badger',
74
+ '6.06' => 'Dapper Drake',
75
+ '6.10' => 'Edgy Eft',
76
+ '7.04' => 'Feisty Fawn',
77
+ '7.10' => 'Gutsy Gibbon',
78
+ '8.04' => 'Hardy Heron',
79
+ '8.10' => 'Intrepid Ibex',
80
+ '9.04' => 'Jaunty Jackalope',
81
+ '9.10' => 'Karmic Koala',
82
+ '10.04' => 'Lucid Lynx',
83
+ '10.10' => 'Maverick Meerkat',
84
+ '11.04' => 'Natty Narwhal'
85
+ },
86
+ :debian => {
87
+ '5.0.4' => 'Lenny'
88
+ }
89
+ },
90
+ :bsd => {
91
+ :dragonfly => {},
92
+ :freebsd => {}
93
+ }
94
+ }
95
+ end
96
+ end
97
+ end