fig 0.1.41 → 0.1.42

Sign up to get free protection for your applications and to get access to all the features.
data/Changes CHANGED
@@ -1,9 +1,19 @@
1
+ v0.1.xx
2
+
3
+ - "file:" protocol works for FIG_REMOTE_HOME.
4
+
5
+ - Testing no longer requires ssh.
6
+
7
+
1
8
  v0.1.41
2
9
 
3
10
  - Release cleanup
4
11
 
12
+
5
13
  v0.1.40
6
14
 
15
+ - Works on Mac (in conjunction with libarchive-static 1.0.1).
16
+
7
17
  - Supports configuration via rc files in JSON format. These can be (in
8
18
  ascending order of priority of values):
9
19
  - in the repository under "_meta/figrc"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.41
1
+ 0.1.42
data/lib/fig.rb CHANGED
@@ -7,6 +7,9 @@ require 'fig/figrc'
7
7
  require 'fig/logging'
8
8
  require 'fig/options'
9
9
  require 'fig/os'
10
+ require 'fig/package'
11
+ require 'fig/package/configuration'
12
+ require 'fig/package/publish'
10
13
  require 'fig/parser'
11
14
  require 'fig/repository'
12
15
  require 'fig/retriever'
@@ -18,9 +21,9 @@ module Fig
18
21
 
19
22
  def parse_descriptor(descriptor)
20
23
  # todo should use treetop for these:
21
- package_name = descriptor =~ /^([^:\/]+)/ ? $1 : nil
22
- config_name = descriptor =~ /:([^:\/]+)/ ? $1 : nil
23
- version_name = descriptor =~ /\/([^:\/]+)/ ? $1 : nil
24
+ package_name = descriptor =~ %r< ^ ( [^:/]+ ) >x ? $1 : nil
25
+ config_name = descriptor =~ %r< : ( [^:/]+ ) >x ? $1 : nil
26
+ version_name = descriptor =~ %r< / ( [^:/]+ ) >x ? $1 : nil
24
27
  return package_name, config_name, version_name
25
28
  end
26
29
 
@@ -129,7 +132,7 @@ module Fig
129
132
  end
130
133
 
131
134
  if input
132
- package = Parser.new.parse_package(nil, nil, '.', input)
135
+ package = Parser.new(configuration).parse_package(nil, nil, '.', input)
133
136
  direct_retrieves=[]
134
137
  if options[:retrieve]
135
138
  package.retrieves.each do |var, path|
@@ -162,8 +165,8 @@ module Fig
162
165
  return 10
163
166
  end
164
167
  if not options[:modifiers].empty?
165
- publish_statements = options[:resources] + options[:archives] + [Configuration.new('default', options[:modifiers])]
166
- publish_statements << Publish.new('default','default')
168
+ publish_statements = options[:resources] + options[:archives] + [Package::Configuration.new('default', options[:modifiers])]
169
+ publish_statements << Package::Publish.new('default','default')
167
170
  elsif not package.statements.empty?
168
171
  publish_statements = package.statements
169
172
  else
@@ -208,7 +211,8 @@ module Fig
208
211
  return_code = run_fig(argv)
209
212
  return return_code
210
213
  rescue URLAccessError => exception
211
- $stderr.puts "Access to #{exception.url} not allowed."
214
+ urls = exception.urls.join(', ')
215
+ $stderr.puts "Access to #{urls} in #{exception.package}/#{exception.version} not allowed."
212
216
  return 1
213
217
  rescue UserInputError => exception
214
218
  # If there's no message, we assume that the cause has already been logged.
@@ -216,6 +220,10 @@ module Fig
216
220
  $stderr.puts exception.to_s
217
221
  end
218
222
 
223
+ return 1
224
+ rescue OptionParser::InvalidOption => exception
225
+ $stderr.puts exception.to_s
226
+ $stderr.puts USAGE
219
227
  return 1
220
228
  end
221
229
  end
@@ -2,6 +2,10 @@ require 'stringio'
2
2
 
3
3
  require 'fig/backtrace'
4
4
  require 'fig/logging'
5
+ require 'fig/package/command'
6
+ require 'fig/package/include'
7
+ require 'fig/package/path'
8
+ require 'fig/package/set'
5
9
  require 'fig/repositoryerror'
6
10
 
7
11
  module Fig
@@ -72,13 +76,13 @@ module Fig
72
76
 
73
77
  def apply_config_statement(base_package, statement, backtrace)
74
78
  case statement
75
- when Path
79
+ when Package::Path
76
80
  append_variable(base_package, statement.name, statement.value)
77
- when Set
81
+ when Package::Set
78
82
  set_variable(base_package, statement.name, statement.value)
79
- when Include
83
+ when Package::Include
80
84
  include_config(base_package, statement.package_name, statement.config_name, statement.version_name, statement.overrides, backtrace)
81
- when Command
85
+ when Package::Command
82
86
  # ignore
83
87
  else
84
88
  fail "Unexpected statement: #{statement}"
@@ -1,4 +1,15 @@
1
1
  require 'fig/package'
2
+ require 'fig/package/archive'
3
+ require 'fig/package/command'
4
+ require 'fig/package/configuration'
5
+ require 'fig/package/include'
6
+ require 'fig/package/install'
7
+ require 'fig/package/override'
8
+ require 'fig/package/path'
9
+ require 'fig/package/publish'
10
+ require 'fig/package/resource'
11
+ require 'fig/package/retrieve'
12
+ require 'fig/package/set'
2
13
 
3
14
  module Fig
4
15
 
@@ -6,7 +17,12 @@ grammar Fig
6
17
  rule package
7
18
  ws statements:(package_statement*) {
8
19
  def to_package(package_name, version_name, directory)
9
- Package.new(package_name, version_name, directory, statements.elements.map { |statement| statement.to_package_statement })
20
+ Package.new(
21
+ package_name,
22
+ version_name,
23
+ directory,
24
+ statements.elements.map { |statement| statement.to_package_statement }
25
+ )
10
26
  end
11
27
  }
12
28
  end
@@ -18,7 +34,7 @@ grammar Fig
18
34
  rule archive
19
35
  "archive" ws url {
20
36
  def to_package_statement
21
- Archive.new(url.value.text_value)
37
+ Package::Archive.new(url.value.text_value)
22
38
  end
23
39
  }
24
40
  end
@@ -26,23 +42,31 @@ grammar Fig
26
42
  rule resource
27
43
  "resource" ws url {
28
44
  def to_package_statement
29
- Resource.new(url.value.text_value)
45
+ Package::Resource.new(url.value.text_value)
30
46
  end
31
47
  }
32
48
  end
33
49
 
34
50
  rule retrieve
35
- "retrieve" ws var:[@a-zA-Z0-9/\._]+ "->" path:[a-zA-Z0-9_/\.\-\[\]]+ ws {
51
+ "retrieve" ws var:retrieve_variable "->" path:retrieve_path ws {
36
52
  def to_package_statement
37
- Retrieve.new(var.text_value, path.text_value)
53
+ Package::Retrieve.new(var.text_value, path.text_value)
38
54
  end
39
55
  }
40
56
  end
41
57
 
58
+ rule retrieve_variable
59
+ [@a-zA-Z0-9/._]+
60
+ end
61
+
62
+ rule retrieve_path
63
+ [a-zA-Z0-9_/.\[\]-]+
64
+ end
65
+
42
66
  rule install
43
67
  "install" ws statements:config_statement* "end" ws {
44
68
  def to_package_statement
45
- Install.new(statements.elements.map { |statement| statement.to_config_statement })
69
+ Package::Install.new(statements.elements.map { |statement| statement.to_config_statement })
46
70
  end
47
71
  }
48
72
  end
@@ -50,7 +74,7 @@ grammar Fig
50
74
  rule config
51
75
  "config" ws config_name ws statements:config_statement* "end" ws {
52
76
  def to_package_statement
53
- Configuration.new(config_name.text_value, statements.elements.map { |statement| statement.to_config_statement })
77
+ Package::Configuration.new(config_name.text_value, statements.elements.map { |statement| statement.to_config_statement })
54
78
  end
55
79
  }
56
80
  end
@@ -65,7 +89,7 @@ grammar Fig
65
89
  package = descriptor.respond_to?(:package) ? descriptor.package.text_value : nil
66
90
  config = descriptor.get_config
67
91
  version = descriptor.get_version
68
- Include.new(package, config, version, overrides.elements.map{ |e| e.to_override })
92
+ Package::Include.new(package, config, version, overrides.elements.map{ |e| e.to_override })
69
93
  end
70
94
  }
71
95
  end
@@ -73,31 +97,47 @@ grammar Fig
73
97
  rule override
74
98
  "override" ws package_name "/" version_name ws {
75
99
  def to_override
76
- return Override.new(package_name.text_value, version_name.text_value)
100
+ return Package::Override.new(package_name.text_value, version_name.text_value)
77
101
  end
78
102
  }
79
103
  end
80
104
 
81
105
  rule path
82
- ("append" / "path" / "add") ws name:[a-zA-Z0-9_]+ "=" value:[@a-zA-Z0-9/\-\\._]+ ws {
106
+ ("append" / "path" / "add") ws name:path_name "=" value:path_value ws {
83
107
  def to_config_statement
84
- Path.new(name.text_value, value.text_value)
108
+ Package::Path.new(name.text_value, value.text_value)
85
109
  end
86
110
  }
87
111
  end
88
112
 
113
+ rule path_name
114
+ [a-zA-Z0-9_]+
115
+ end
116
+
117
+ rule path_value
118
+ [@a-zA-Z0-9/\\._-]+
119
+ end
120
+
89
121
  rule set
90
- "set" ws name:[a-zA-Z0-9_]+ "=" value:[@a-zA-Z0-9/\-\\._]+ ws {
122
+ "set" ws name:set_name "=" value:set_value ws {
91
123
  def to_config_statement
92
- Set.new(name.text_value, value.text_value)
124
+ Package::Set.new(name.text_value, value.text_value)
93
125
  end
94
126
  }
95
127
  end
96
128
 
129
+ rule set_name
130
+ [a-zA-Z0-9_]+
131
+ end
132
+
133
+ rule set_value
134
+ [@a-zA-Z0-9/\\._-]+
135
+ end
136
+
97
137
  rule command
98
138
  "command" ws string {
99
139
  def to_config_statement
100
- Command.new(string.value.text_value)
140
+ Package::Command.new(string.value.text_value)
101
141
  end
102
142
  }
103
143
  end
@@ -134,11 +174,11 @@ grammar Fig
134
174
  end
135
175
 
136
176
  rule version_name
137
- [a-zA-Z0-9_\-.]+
177
+ [a-zA-Z0-9_.-]+
138
178
  end
139
179
 
140
180
  rule config_name
141
- [a-zA-Z0-9_\-.]+
181
+ [a-zA-Z0-9_.-]+
142
182
  end
143
183
 
144
184
  rule name
@@ -146,7 +186,7 @@ grammar Fig
146
186
  end
147
187
 
148
188
  rule url
149
- (value:[a-zA-Z0-9:/\-\\._\*]+ ws) / ('"' value:[a-zA-Z0-9:/\-\\._]+ '"' ws)
189
+ (value:[a-zA-Z0-9:/\\._*-]+ ws) / ('"' value:[a-zA-Z0-9:/\\._-]+ '"' ws)
150
190
  end
151
191
 
152
192
  rule ws
data/lib/fig/options.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  require 'optparse'
2
2
  require 'fig/package'
3
+ require 'fig/package/archive'
4
+ require 'fig/package/include'
5
+ require 'fig/package/path'
6
+ require 'fig/package/resource'
7
+ require 'fig/package/set'
3
8
 
4
9
  module Fig
5
10
  def parse_descriptor(descriptor)
@@ -66,7 +71,7 @@ EOF
66
71
  'append (actually, prepend) VAL to environment var VAR, delimited by separator'
67
72
  ) do |var_val|
68
73
  var, val = var_val.split('=')
69
- options[:modifiers] << Path.new(var, val)
74
+ options[:modifiers] << Package::Path.new(var, val)
70
75
  end
71
76
 
72
77
  options[:archives] = []
@@ -74,7 +79,7 @@ EOF
74
79
  '--archive FULLPATH',
75
80
  'include FULLPATH archive in package (when using --publish)'
76
81
  ) do |path|
77
- options[:archives] << Archive.new(path)
82
+ options[:archives] << Package::Archive.new(path)
78
83
  end
79
84
 
80
85
  options[:cleans] = []
@@ -127,7 +132,7 @@ EOF
127
132
  'include PKG (with any variable prepends) in environment'
128
133
  ) do |descriptor|
129
134
  package_name, config_name, version_name = parse_descriptor(descriptor)
130
- options[:modifiers] << Include.new(package_name, config_name, version_name, {})
135
+ options[:modifiers] << Package::Include.new(package_name, config_name, version_name, {})
131
136
  end
132
137
 
133
138
  options[:list] = false
@@ -179,14 +184,14 @@ EOF
179
184
  '--resource FULLPATH',
180
185
  'include FULLPATH resource in package (when using --publish)'
181
186
  ) do |path|
182
- options[:resources] << Resource.new(path)
187
+ options[:resources] << Package::Resource.new(path)
183
188
  end
184
189
 
185
190
  opts.on(
186
191
  '-s', '--set VAR=VAL', 'set environment variable VAR to VAL'
187
192
  ) do |var_val|
188
193
  var, val = var_val.split('=')
189
- options[:modifiers] << Set.new(var, val)
194
+ options[:modifiers] << Package::Set.new(var, val)
190
195
  end
191
196
 
192
197
  options[:update] = false
data/lib/fig/os.rb CHANGED
@@ -68,12 +68,22 @@ module Fig
68
68
  NOT_MODIFIED = 3
69
69
  NOT_FOUND = 4
70
70
 
71
+ def strip_paths_for_list(ls_output, packages, path)
72
+ if not ls_output.nil?
73
+ ls_output = ls_output.gsub(path + '/', '').gsub(path, '').split("\n")
74
+ ls_output.each do |line|
75
+ parts = line.gsub(/\\/, '/').sub(/^\.\//, '').sub(/:$/, '').chomp().split('/')
76
+ packages << parts.join('/') if parts.size == 2
77
+ end
78
+ end
79
+ end
80
+
71
81
  def download_list(url)
72
82
  begin
73
83
  uri = URI.parse(url)
74
84
  rescue
75
85
  Logging.fatal %Q<Unable to parse url: "#{url}">
76
- raise NetworkError.new
86
+ raise NetworkError.new(%Q<Unable to parse url: "#{url}">)
77
87
  end
78
88
  case uri.scheme
79
89
  when 'ftp'
@@ -88,18 +98,17 @@ module Fig
88
98
  packages = []
89
99
  Net::SSH.start(uri.host, uri.user) do |ssh|
90
100
  ls = ssh.exec!("[ -d #{uri.path} ] && find #{uri.path}")
91
- if not ls.nil?
92
- ls = ls.gsub(uri.path + '/', '').gsub(uri.path, '').split("\n")
93
- ls.each do |line|
94
- parts = line.gsub(/\\/, '/').sub(/^\.\//, '').sub(/:$/, '').chomp().split('/')
95
- packages << parts.join('/') if parts.size == 2
96
- end
97
- end
101
+ strip_paths_for_list(ls, packages, uri.path)
98
102
  end
99
103
  packages
104
+ when 'file'
105
+ packages = []
106
+ ls = %x<[ -d #{uri.path} ] && find #{uri.path}>
107
+ strip_paths_for_list(ls, packages, uri.path)
108
+ return packages
100
109
  else
101
110
  Logging.fatal "Protocol not supported: #{url}"
102
- raise NetworkError.new
111
+ raise NetworkError.new("Protocol not supported: #{url}")
103
112
  end
104
113
  end
105
114
 
@@ -170,9 +179,15 @@ module Fig
170
179
  cmd = `which fig-download`.strip + " #{timestamp} #{uri.path}"
171
180
  log_download(url, path)
172
181
  ssh_download(uri.user, uri.host, path, cmd)
182
+ when 'file'
183
+ begin
184
+ FileUtils.cp(uri.path, path)
185
+ rescue Errno::ENOENT => e
186
+ raise NotFoundError.new
187
+ end
173
188
  else
174
189
  Logging.fatal "Unknown protocol: #{url}"
175
- raise NetworkError.new
190
+ raise NetworkError.new("Unknown protocol: #{url}")
176
191
  end
177
192
  end
178
193
 
@@ -197,7 +212,7 @@ module Fig
197
212
  unpack_archive(dir, path)
198
213
  else
199
214
  Logging.fatal "Unknown archive type: #{basename}"
200
- raise NetworkError.new
215
+ raise NetworkError.new("Unknown archive type: #{basename}")
201
216
  end
202
217
  end
203
218
 
@@ -233,6 +248,12 @@ module Fig
233
248
  end
234
249
  ftp.putbinaryfile(local_file)
235
250
  end
251
+ when 'file'
252
+ FileUtils.mkdir_p(File.dirname(uri.path))
253
+ FileUtils.cp(local_file, uri.path)
254
+ else
255
+ Logging.fatal "Unknown protocol: #{uri}"
256
+ raise NetworkError.new("Unknown protocol: #{uri}")
236
257
  end
237
258
  end
238
259
 
@@ -371,7 +392,7 @@ module Fig
371
392
  else
372
393
  tempfile.delete
373
394
  Logging.fatal "Unable to download file #{path}: #{return_code}"
374
- raise NetworkError.new
395
+ raise NetworkError.new("Unable to download file #{path}: #{return_code}")
375
396
  end
376
397
  end
377
398
 
data/lib/fig/package.rb CHANGED
@@ -1,216 +1,69 @@
1
1
  require 'fig/logging'
2
2
  require 'fig/packageerror'
3
-
4
- module Fig
5
- class Package
6
- attr_reader :package_name, :version_name, :directory, :statements
7
- attr_accessor :backtrace
8
-
9
- def initialize(package_name, version_name, directory, statements)
10
- @package_name = package_name
11
- @version_name = version_name
12
- @directory = directory
13
- @statements = statements
14
- @backtrace = nil
15
- end
16
-
17
- def [](config_name)
18
- @statements.each do |stmt|
19
- return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
20
- end
21
- Fig::Logging.fatal "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
22
- raise PackageError.new
23
- end
24
-
25
- def configs
26
- @statements.select { |statement| statement.is_a?(Configuration) }
27
- end
28
-
29
- def retrieves
30
- retrieves = {}
31
- statements.each { |statement| retrieves[statement.var] = statement.path if statement.is_a?(Retrieve) }
32
- retrieves
33
- end
34
-
35
- def archive_urls
36
- @statements.select{|s| s.is_a?(Archive)}.map{|s|s.url}
37
- end
38
-
39
- def resource_urls
40
- @statements.select{|s| s.is_a?(Resource)}.map{|s|s.url}
41
- end
42
-
43
- def unparse
44
- @statements.map { |statement| statement.unparse('') }.join("\n")
45
- end
46
-
47
- def ==(other)
48
- @package_name == other.package_name && @version_name == other.version_name && @statements.to_yaml == other.statements.to_yaml
49
- end
50
-
51
- def to_s
52
- @package_name + '/' + @version_name
53
- end
3
+ require 'fig/package/archive'
4
+ require 'fig/package/configuration'
5
+ require 'fig/package/resource'
6
+ require 'fig/package/retrieve'
7
+
8
+ module Fig; end
9
+
10
+ class Fig::Package
11
+ attr_reader :package_name, :version_name, :directory, :statements
12
+ attr_accessor :backtrace
13
+
14
+ def initialize(package_name, version_name, directory, statements)
15
+ @package_name = package_name
16
+ @version_name = version_name
17
+ @directory = directory
18
+ @statements = statements
19
+ @backtrace = nil
54
20
  end
55
21
 
56
- class Archive
57
- attr_reader :url
58
-
59
- def initialize(url)
60
- @url = url
61
- end
62
-
63
- def unparse(indent)
64
- %Q<#{indent}archive "#{url}">
22
+ def [](config_name)
23
+ @statements.each do |stmt|
24
+ return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
65
25
  end
26
+ Fig::Logging.fatal "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
27
+ raise PackageError.new
66
28
  end
67
29
 
68
- class Resource
69
- attr_reader :url
70
-
71
- def initialize(url)
72
- @url = url
73
- end
74
-
75
- def unparse(indent)
76
- "#{indent}resource #{url}"
77
- end
30
+ def configs
31
+ @statements.select { |statement| statement.is_a?(Configuration) }
78
32
  end
79
33
 
80
- class Retrieve
81
- attr_reader :var, :path
82
-
83
- def initialize(var, path)
84
- @var = var
85
- @path = path
86
- end
87
-
88
- def unparse(indent)
89
- "#{indent}retrieve #{var}->#{path}"
90
- end
34
+ def retrieves
35
+ retrieves = {}
36
+ statements.each { |statement| retrieves[statement.var] = statement.path if statement.is_a?(Retrieve) }
37
+ retrieves
91
38
  end
92
39
 
93
- class Publish
94
- attr_reader :local_name, :remote_name
95
-
96
- def initialize(local_name, remote_name)
97
- @local_name = local_name
98
- @remote_name = remote_name
99
- end
100
-
101
- def unparse(indent)
102
- "#{indent}publish #{@local_name}->#{@remote_name}"
103
- end
40
+ def archive_urls
41
+ @statements.select{|s| s.is_a?(Archive)}.map{|s|s.url}
104
42
  end
105
43
 
106
- class Install
107
- def initialize(statements)
108
- @statements = statements
109
- end
110
-
111
- def unparse(indent)
112
- prefix = "\n#{indent}install"
113
- body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
114
- suffix = "#{indent}end"
115
- return [prefix, body, suffix].join("\n")
116
- end
117
- end
118
-
119
- class Configuration
120
- attr_reader :name, :statements
121
-
122
- def initialize(name, statements)
123
- @name = name
124
- @statements = statements
125
- end
126
-
127
- def with_name(name)
128
- Configuration.new(name, statements)
129
- end
130
-
131
- def commands
132
- result = statements.select { |statement| statement.is_a?(Command) }
133
- result
134
- end
135
-
136
- def unparse(indent)
137
- unparse_statements(indent, "config #{@name}", @statements, 'end')
138
- end
139
- end
140
-
141
- class Path
142
- attr_reader :name, :value
143
-
144
- def initialize(name, value)
145
- @name = name
146
- @value = value
147
- end
148
-
149
- def unparse(indent)
150
- "#{indent}append #{name}=#{value}"
151
- end
44
+ def resource_urls
45
+ @statements.select{|s| s.is_a?(Resource)}.map{|s|s.url}
152
46
  end
153
47
 
154
- class Set
155
- attr_reader :name, :value
156
-
157
- def initialize(name, value)
158
- @name = name
159
- @value = value
160
- end
161
-
162
- def unparse(indent)
163
- "#{indent}set #{name}=#{value}"
48
+ def walk_statements(&block)
49
+ @statements.each do |statement|
50
+ yield statement
51
+ statement.walk_statements &block
164
52
  end
165
53
  end
166
54
 
167
- class Include
168
- attr_reader :package_name, :config_name, :version_name, :overrides
169
-
170
- def initialize(package_name, config_name, version_name, overrides)
171
- @package_name = package_name
172
- @config_name = config_name
173
- @version_name = version_name
174
- @overrides = overrides
175
- end
176
-
177
- def unparse(indent)
178
- descriptor = ''
179
- descriptor += @package_name if @package_name
180
- descriptor += "/#{@version_name}" if @version_name
181
- descriptor += ":#{@config_name}" if @config_name
182
- @overrides.each do |override|
183
- descriptor += override.unparse
184
- end
185
- return "#{indent}include #{descriptor}"
186
- end
55
+ def unparse
56
+ @statements.map { |statement| statement.unparse('') }.join("\n")
187
57
  end
188
58
 
189
- class Override
190
- attr_reader :package_name, :version_name
191
-
192
- def initialize(package_name, version_name)
193
- @package_name = package_name
194
- @version_name = version_name
195
- end
196
-
197
- def unparse()
198
- return ' override ' + @package_name + '/' + @version_name
199
- end
59
+ def ==(other)
60
+ return false if other.nil?
61
+ @package_name == other.package_name && @version_name == other.version_name && @statements.to_yaml == other.statements.to_yaml
200
62
  end
201
63
 
202
- class Command
203
- attr_reader :command
204
-
205
- def initialize(command)
206
- @command = command
207
- end
208
-
209
- def unparse(indent)
210
- %Q<#{indent}command "#{@command}">
211
- end
64
+ def to_s
65
+ @package_name + '/' + @version_name
212
66
  end
213
-
214
67
  end
215
68
 
216
69
  def unparse_statements(indent, prefix, statements, suffix)