fig18 0.1.50-i386-mingw32 → 0.1.51-i386-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes +4 -0
- data/VERSION +1 -1
- data/lib/fig/applicationconfiguration.rb +2 -1
- data/lib/fig/backtrace.rb +2 -0
- data/lib/fig/environment.rb +35 -24
- data/lib/fig/figrc.rb +2 -0
- data/lib/fig/grammar.treetop +1 -1
- data/lib/fig/log4rconfigerror.rb +1 -0
- data/lib/fig/logging.rb +2 -0
- data/lib/fig/notfounderror.rb +3 -0
- data/lib/fig/options.rb +20 -14
- data/lib/fig/os.rb +2 -0
- data/lib/fig/package/archive.rb +3 -0
- data/lib/fig/package/command.rb +2 -0
- data/lib/fig/package/configuration.rb +3 -3
- data/lib/fig/package/include.rb +2 -0
- data/lib/fig/package/install.rb +1 -0
- data/lib/fig/package/override.rb +7 -0
- data/lib/fig/package/path.rb +2 -0
- data/lib/fig/package/publish.rb +2 -0
- data/lib/fig/package/resource.rb +3 -0
- data/lib/fig/package/retrieve.rb +1 -0
- data/lib/fig/package/set.rb +1 -0
- data/lib/fig/package/statement.rb +1 -0
- data/lib/fig/package.rb +8 -7
- data/lib/fig/packageerror.rb +2 -1
- data/lib/fig/parser.rb +34 -8
- data/lib/fig/repository.rb +2 -0
- data/lib/fig/retriever.rb +7 -6
- data/lib/fig/urlaccesserror.rb +1 -0
- data/lib/fig/userinputerror.rb +2 -0
- data/lib/fig/windows.rb +1 -3
- data/lib/fig.rb +184 -140
- metadata +182 -303
data/Changes
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.51
|
data/lib/fig/backtrace.rb
CHANGED
data/lib/fig/environment.rb
CHANGED
@@ -7,23 +7,31 @@ require 'fig/package/include'
|
|
7
7
|
require 'fig/package/path'
|
8
8
|
require 'fig/package/set'
|
9
9
|
require 'fig/repositoryerror'
|
10
|
+
require 'fig/userinputerror'
|
10
11
|
|
11
12
|
module Fig
|
12
|
-
#
|
13
|
-
#
|
13
|
+
# Manages the program's metadata, including packages and environment
|
14
|
+
# variables, and sets things up for running commands (from "command"
|
15
|
+
# statements in configuration files).
|
14
16
|
class Environment
|
15
17
|
DEFAULT_VERSION_NAME = 'current'
|
16
18
|
|
17
|
-
def initialize(os, repository,
|
19
|
+
def initialize(os, repository, variables_override, retriever)
|
18
20
|
@os = os
|
19
21
|
@repository = repository
|
20
|
-
@variables =
|
22
|
+
@variables = variables_override || get_environment_variables
|
21
23
|
@retrieve_vars = {}
|
22
24
|
@packages = {}
|
23
25
|
@applied_configs = {}
|
24
26
|
@retriever = retriever
|
25
27
|
end
|
26
28
|
|
29
|
+
def get_environment_variables
|
30
|
+
vars = {}
|
31
|
+
ENV.each { |key,value| vars[key]=value }
|
32
|
+
return vars
|
33
|
+
end
|
34
|
+
|
27
35
|
# Returns the value of an envirionment variable
|
28
36
|
def [](name)
|
29
37
|
@variables[name]
|
@@ -60,26 +68,35 @@ module Fig
|
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
63
|
-
def
|
71
|
+
def execute_command(command, args, package)
|
72
|
+
with_environment do
|
73
|
+
argument =
|
74
|
+
expand_command_line_argument(
|
75
|
+
"#{command.command} #{args.join(' ')}"
|
76
|
+
)
|
77
|
+
|
78
|
+
yield expand_path(argument, package).split(' ')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_config_name_in_package(package_name)
|
83
|
+
return @applied_configs.key?(package_name) ? @applied_configs[package_name].first : 'default'
|
84
|
+
end
|
85
|
+
|
86
|
+
def execute_config(base_package, package_name, config_name, version_name, args, &block)
|
87
|
+
config_name ||= find_config_name_in_package(package_name)
|
64
88
|
package = lookup_package(
|
65
89
|
package_name || base_package.package_name,
|
66
90
|
version_name,
|
67
91
|
Backtrace.new(nil, package_name, version_name, config_name)
|
68
92
|
)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
expand_command_line_argument(
|
76
|
-
"#{command.command} #{args.join(' ')}"
|
77
|
-
)
|
78
|
-
|
79
|
-
result = yield expand_path(argument, package).split(' ')
|
80
|
-
end
|
93
|
+
|
94
|
+
command = package[config_name].command
|
95
|
+
if command
|
96
|
+
execute_command(command, args, package, &block)
|
97
|
+
else
|
98
|
+
raise UserInputError.new(%Q<The "#{package.to_s}" package with the "#{config_name}" configuration does not contain a command.>)
|
81
99
|
end
|
82
|
-
result
|
83
100
|
end
|
84
101
|
|
85
102
|
def apply_config_statement(base_package, statement, backtrace)
|
@@ -113,12 +130,6 @@ module Fig
|
|
113
130
|
apply_config(package, config_name || 'default', new_backtrace)
|
114
131
|
end
|
115
132
|
|
116
|
-
def direct_retrieve(package_name, source_path, target_path)
|
117
|
-
package = lookup_package(package_name, nil, nil)
|
118
|
-
FileUtils.mkdir_p(target_path)
|
119
|
-
FileUtils.cp_r(File.join(package.directory, source_path, '.'), target_path)
|
120
|
-
end
|
121
|
-
|
122
133
|
private
|
123
134
|
|
124
135
|
def set_variable(base_package, name, value)
|
data/lib/fig/figrc.rb
CHANGED
@@ -7,6 +7,8 @@ require 'fig/os'
|
|
7
7
|
REPOSITORY_CONFIGURATION = '_meta/figrc'
|
8
8
|
|
9
9
|
module Fig
|
10
|
+
# Parse multiple figrc files and assemble them into a single
|
11
|
+
# ApplicationConfiguration object.
|
10
12
|
class FigRC
|
11
13
|
def self.find(
|
12
14
|
override_path, repository_url, login, fig_home, disable_figrc = false
|
data/lib/fig/grammar.treetop
CHANGED
data/lib/fig/log4rconfigerror.rb
CHANGED
data/lib/fig/logging.rb
CHANGED
@@ -7,6 +7,8 @@ require 'fig/log4rconfigerror'
|
|
7
7
|
|
8
8
|
module Fig; end
|
9
9
|
|
10
|
+
# Logging facility that handles the fact that we may wish to do logging prior
|
11
|
+
# to Log4r being properly configured.
|
10
12
|
module Fig::Logging
|
11
13
|
if not Log4r::Logger['initial']
|
12
14
|
@@logger = Log4r::Logger.new('initial')
|
data/lib/fig/notfounderror.rb
CHANGED
data/lib/fig/options.rb
CHANGED
@@ -6,6 +6,9 @@ require 'fig/package/path'
|
|
6
6
|
require 'fig/package/resource'
|
7
7
|
require 'fig/package/set'
|
8
8
|
|
9
|
+
# Command-line processing.
|
10
|
+
|
11
|
+
|
9
12
|
module Fig
|
10
13
|
def parse_descriptor(descriptor)
|
11
14
|
# todo should use treetop for these:
|
@@ -17,7 +20,10 @@ module Fig
|
|
17
20
|
|
18
21
|
USAGE = <<EOF
|
19
22
|
|
20
|
-
Usage: fig [--
|
23
|
+
Usage: fig [--update | --update-if-missing] [--file <path>] [--set <VAR=value>] [--config <config>] [--login] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc] [-- <command>]
|
24
|
+
fig [--publish | --publish-local] [--append <VAR=val>] [--resource <fullpath>] [--include <package name/version>] [--force] [--no-file] [--archive <path>] [--file] [--set <VAR=value>] [--config <config>] [--login] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc]
|
25
|
+
fig [--set <VAR=value>] [--get <VAR> | --list-configs <package name>/<version> | --list | --list-remote | --clean <package name/version> | --version] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc] [-- <command>]
|
26
|
+
fig [<package name>/<version>] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc]
|
21
27
|
|
22
28
|
Relevant env vars: FIG_REMOTE_URL (required), FIG_HOME (path to local repository cache, defaults
|
23
29
|
to $HOME/.fighome).
|
@@ -64,14 +70,14 @@ EOF
|
|
64
70
|
return nil, nil, 0
|
65
71
|
end
|
66
72
|
|
67
|
-
options[:
|
73
|
+
options[:non_command_package_statements] = []
|
68
74
|
opts.on(
|
69
75
|
'-p',
|
70
76
|
'--append VAR=VAL',
|
71
77
|
'append (actually, prepend) VAL to environment var VAR, delimited by separator'
|
72
78
|
) do |var_val|
|
73
79
|
var, val = var_val.split('=')
|
74
|
-
options[:
|
80
|
+
options[:non_command_package_statements] << Package::Path.new(var, val)
|
75
81
|
end
|
76
82
|
|
77
83
|
options[:archives] = []
|
@@ -96,11 +102,6 @@ EOF
|
|
96
102
|
options[:config] = config
|
97
103
|
end
|
98
104
|
|
99
|
-
options[:debug] = false
|
100
|
-
opts.on('-d', '--debug', 'print debug info') do
|
101
|
-
options[:debug] = true
|
102
|
-
end
|
103
|
-
|
104
105
|
options[:package_config_file] = nil
|
105
106
|
opts.on(
|
106
107
|
'--file FILE',
|
@@ -117,13 +118,13 @@ EOF
|
|
117
118
|
options[:force] = force
|
118
119
|
end
|
119
120
|
|
120
|
-
options[:
|
121
|
+
options[:get] = nil
|
121
122
|
opts.on(
|
122
123
|
'-g',
|
123
124
|
'--get VAR',
|
124
125
|
'print value of environment variable VAR'
|
125
|
-
) do |
|
126
|
-
options[:
|
126
|
+
) do |get|
|
127
|
+
options[:get] = get
|
127
128
|
end
|
128
129
|
|
129
130
|
opts.on(
|
@@ -132,7 +133,7 @@ EOF
|
|
132
133
|
'include PKG (with any variable prepends) in environment'
|
133
134
|
) do |descriptor|
|
134
135
|
package_name, config_name, version_name = parse_descriptor(descriptor)
|
135
|
-
options[:
|
136
|
+
options[:non_command_package_statements] << Package::Include.new(package_name, config_name, version_name, {})
|
136
137
|
end
|
137
138
|
|
138
139
|
options[:list] = false
|
@@ -191,7 +192,7 @@ EOF
|
|
191
192
|
'-s', '--set VAR=VAL', 'set environment variable VAR to VAL'
|
192
193
|
) do |var_val|
|
193
194
|
var, val = var_val.split('=')
|
194
|
-
options[:
|
195
|
+
options[:non_command_package_statements] << Package::Set.new(var, val)
|
195
196
|
end
|
196
197
|
|
197
198
|
options[:update] = false
|
@@ -241,7 +242,12 @@ EOF
|
|
241
242
|
end
|
242
243
|
|
243
244
|
# Need to catch the exception thrown from parser and retranslate into a fig exception
|
244
|
-
|
245
|
+
begin
|
246
|
+
parser.parse!(argv)
|
247
|
+
rescue OptionParser::MissingArgument => error
|
248
|
+
$stderr.puts "Please provide the #{error}."
|
249
|
+
return nil, nil, 1
|
250
|
+
end
|
245
251
|
|
246
252
|
return options, argv, nil
|
247
253
|
end
|
data/lib/fig/os.rb
CHANGED
data/lib/fig/package/archive.rb
CHANGED
@@ -5,6 +5,9 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# Specifies an archive file (possibly via a URL) that is part of the current package.
|
9
|
+
#
|
10
|
+
# Differs from a Resource in that the contents will be extracted.
|
8
11
|
class Fig::Package::Archive
|
9
12
|
include Fig::Package::Statement
|
10
13
|
|
data/lib/fig/package/command.rb
CHANGED
@@ -5,6 +5,8 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# Specifies a default command that will be executed for a given Configuration
|
9
|
+
# if no command is specified on the command-line.
|
8
10
|
class Fig::Package::Command
|
9
11
|
include Fig::Package::Statement
|
10
12
|
|
@@ -6,6 +6,7 @@ require 'fig/package/statement'
|
|
6
6
|
module Fig; end
|
7
7
|
class Fig::Package; end
|
8
8
|
|
9
|
+
# A grouping of statements within a configuration. May not be nested.
|
9
10
|
class Fig::Package::Configuration
|
10
11
|
include Fig::Package::Statement
|
11
12
|
|
@@ -20,11 +21,10 @@ class Fig::Package::Configuration
|
|
20
21
|
Configuration.new(name, statements)
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
24
|
+
def command
|
25
|
+
return statements.find do
|
25
26
|
|statement| statement.is_a?(Fig::Package::Command)
|
26
27
|
end
|
27
|
-
result
|
28
28
|
end
|
29
29
|
|
30
30
|
def walk_statements(&block)
|
data/lib/fig/package/include.rb
CHANGED
@@ -5,6 +5,8 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# Dual role: "include :configname" incorporates one configuration into another;
|
9
|
+
# "include package[/version]" declares a dependency upon another package.
|
8
10
|
class Fig::Package::Include
|
9
11
|
include Fig::Package::Statement
|
10
12
|
|
data/lib/fig/package/install.rb
CHANGED
data/lib/fig/package/override.rb
CHANGED
@@ -5,6 +5,13 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# Overrides one package version dependency with another in an include
|
9
|
+
# statement.
|
10
|
+
#
|
11
|
+
# include blah/1.2.3 override somedependency/3.2.6
|
12
|
+
#
|
13
|
+
# indicates that, regardless of which version of somedependency the blah
|
14
|
+
# package says it needs, the blah package will actually use v3.2.6.
|
8
15
|
class Fig::Package::Override
|
9
16
|
include Fig::Package::Statement
|
10
17
|
|
data/lib/fig/package/path.rb
CHANGED
@@ -5,6 +5,8 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# A statement that specifies or modifies a path environment variable, e.g.
|
9
|
+
# "append", "path", "add" (though those are all synonyms).
|
8
10
|
class Fig::Package::Path
|
9
11
|
include Fig::Package::Statement
|
10
12
|
|
data/lib/fig/package/publish.rb
CHANGED
data/lib/fig/package/resource.rb
CHANGED
@@ -5,6 +5,9 @@ require 'fig/package/statement'
|
|
5
5
|
module Fig; end
|
6
6
|
class Fig::Package; end
|
7
7
|
|
8
|
+
# Specifies a file (possibly via a URL) that is part of the current package.
|
9
|
+
#
|
10
|
+
# Differs from an Archive in that the contents will not be extracted.
|
8
11
|
class Fig::Package::Resource
|
9
12
|
include Fig::Package::Statement
|
10
13
|
|
data/lib/fig/package/retrieve.rb
CHANGED
data/lib/fig/package/set.rb
CHANGED
data/lib/fig/package.rb
CHANGED
@@ -7,13 +7,15 @@ require 'fig/package/retrieve'
|
|
7
7
|
|
8
8
|
module Fig; end
|
9
9
|
|
10
|
+
# The parsed representation of a configuration file. Contains the statement
|
11
|
+
# objects.
|
10
12
|
class Fig::Package
|
11
13
|
attr_reader :package_name, :version_name, :directory, :statements
|
12
14
|
attr_accessor :backtrace
|
13
15
|
|
14
16
|
def initialize(package_name, version_name, directory, statements)
|
15
|
-
@package_name = package_name
|
16
|
-
@version_name = version_name
|
17
|
+
@package_name = package_name
|
18
|
+
@version_name = version_name
|
17
19
|
@directory = directory
|
18
20
|
@statements = statements
|
19
21
|
@backtrace = nil
|
@@ -23,9 +25,7 @@ class Fig::Package
|
|
23
25
|
@statements.each do |stmt|
|
24
26
|
return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
|
25
27
|
end
|
26
|
-
message =
|
27
|
-
"Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
|
28
|
-
Fig::Logging.fatal message
|
28
|
+
message = "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
|
29
29
|
raise Fig::PackageError.new message
|
30
30
|
end
|
31
31
|
|
@@ -64,7 +64,9 @@ class Fig::Package
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def to_s
|
67
|
-
|
67
|
+
package_name ||= 'uninitialized'
|
68
|
+
version_name ||= 'uninitialized'
|
69
|
+
package_name + '/' + version_name
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
@@ -72,4 +74,3 @@ def unparse_statements(indent, prefix, statements, suffix)
|
|
72
74
|
body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
|
73
75
|
return ["\n#{indent}#{prefix}", body, "#{indent}#{suffix}"].join("\n")
|
74
76
|
end
|
75
|
-
|
data/lib/fig/packageerror.rb
CHANGED
data/lib/fig/parser.rb
CHANGED
@@ -6,22 +6,17 @@ require 'fig/logging'
|
|
6
6
|
require 'fig/packageerror'
|
7
7
|
require 'fig/repository'
|
8
8
|
require 'fig/urlaccesserror'
|
9
|
+
require 'fig/userinputerror'
|
9
10
|
|
10
11
|
module Fig
|
12
|
+
# Parses configuration files and deals with a few restrictions on them.
|
11
13
|
class Parser
|
12
14
|
def initialize(application_config)
|
13
15
|
@parser = FigParser.new
|
14
16
|
@application_config = application_config
|
15
17
|
end
|
16
18
|
|
17
|
-
def
|
18
|
-
input = input.gsub(/#.*$/, '')
|
19
|
-
result = @parser.parse(" #{input} ")
|
20
|
-
if result.nil?
|
21
|
-
Logging.fatal "#{directory}: #{@parser.failure_reason}"
|
22
|
-
raise PackageError.new("#{directory}: #{@parser.failure_reason}")
|
23
|
-
end
|
24
|
-
package = result.to_package(package_name, version_name, directory)
|
19
|
+
def find_bad_urls(package, package_name, version_name)
|
25
20
|
bad_urls = []
|
26
21
|
package.walk_statements do |statement|
|
27
22
|
statement.urls.each do |url|
|
@@ -30,7 +25,38 @@ module Fig
|
|
30
25
|
bad_urls << url if not @application_config.url_access_allowed?(url)
|
31
26
|
end
|
32
27
|
end
|
28
|
+
|
33
29
|
raise URLAccessError.new(bad_urls, package_name, version_name) if not bad_urls.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_multiple_command_statements(package)
|
33
|
+
command_processed = false
|
34
|
+
package.walk_statements do |statement|
|
35
|
+
if statement.is_a?(Package::Command)
|
36
|
+
if command_processed == true
|
37
|
+
raise UserInputError.new("Multiple command statements cannot be processed.")
|
38
|
+
end
|
39
|
+
command_processed = true
|
40
|
+
elsif statement.is_a?(Package::Configuration)
|
41
|
+
command_processed = false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_package(package_name, version_name, directory, input)
|
47
|
+
input = input.gsub(/#.*$/, '')
|
48
|
+
result = @parser.parse(" #{input} ")
|
49
|
+
|
50
|
+
if result.nil?
|
51
|
+
Logging.fatal "#{directory}: #{@parser.failure_reason}"
|
52
|
+
raise PackageError.new("#{directory}: #{@parser.failure_reason}")
|
53
|
+
end
|
54
|
+
|
55
|
+
package = result.to_package(package_name, version_name, directory)
|
56
|
+
|
57
|
+
find_bad_urls(package, package_name, version_name)
|
58
|
+
find_multiple_command_statements(package)
|
59
|
+
|
34
60
|
return package
|
35
61
|
end
|
36
62
|
end
|
data/lib/fig/repository.rb
CHANGED
@@ -7,6 +7,8 @@ require 'fig/repositoryerror'
|
|
7
7
|
require 'fig/urlaccesserror'
|
8
8
|
|
9
9
|
module Fig
|
10
|
+
# Overall management of a repository. Handles local operations itself;
|
11
|
+
# defers remote operations to others.
|
10
12
|
class Repository
|
11
13
|
def self.is_url?(url)
|
12
14
|
not (/ftp:\/\/|http:\/\/|file:\/\/|ssh:\/\// =~ url).nil?
|
data/lib/fig/retriever.rb
CHANGED
@@ -3,11 +3,11 @@ require 'set'
|
|
3
3
|
|
4
4
|
require 'fig/logging'
|
5
5
|
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# package/versions they came from, and deletes files as necessary to ensure
|
9
|
-
# we never have files from two different versions of the same package in
|
10
|
-
# working directory.
|
6
|
+
# Copies files from the project directories in FIG_HOME to the user's working
|
7
|
+
# directory. It keeps track of which files have already been copied, and which
|
8
|
+
# package/versions they came from, and deletes files as necessary to ensure
|
9
|
+
# that we never have files from two different versions of the same package in
|
10
|
+
# the user's working directory.
|
11
11
|
class Retriever
|
12
12
|
def initialize(base_dir)
|
13
13
|
@base_dir = base_dir
|
@@ -55,7 +55,7 @@ class Retriever
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
private
|
58
|
+
private
|
59
59
|
|
60
60
|
def load(file)
|
61
61
|
File.open(file).each_line do |line|
|
@@ -108,6 +108,7 @@ private
|
|
108
108
|
Fig::Logging.info "+ [#{@config.name}/#{@config.version}] #{relpath}"
|
109
109
|
end
|
110
110
|
FileUtils.mkdir_p(File.dirname(target))
|
111
|
+
|
111
112
|
FileUtils.cp(source, target, :preserve => true)
|
112
113
|
end
|
113
114
|
@config.files << relpath if @config
|
data/lib/fig/urlaccesserror.rb
CHANGED
data/lib/fig/userinputerror.rb
CHANGED
data/lib/fig/windows.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# Keeping Windows-specific implementation details here.
|
2
|
-
|
3
1
|
require 'erb'
|
4
2
|
require 'fileutils'
|
5
3
|
|
@@ -8,8 +6,8 @@ require 'fileutils'
|
|
8
6
|
# on the fly to run a user supplied command.
|
9
7
|
|
10
8
|
module Fig
|
9
|
+
# Windows-specific implementation details.
|
11
10
|
class Windows
|
12
|
-
|
13
11
|
BATCH_SCRIPT_TEMPLATE = <<EOF
|
14
12
|
@echo off
|
15
13
|
% ENV.each do |k,v|
|