rumodule 0.0.3
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.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +11 -0
- data/LICENSE +20 -0
- data/README.rdoc +218 -0
- data/bin/rumodule +1069 -0
- data/doc/CmdAdd.html +837 -0
- data/doc/CmdDisplay.html +260 -0
- data/doc/CmdHelp.html +304 -0
- data/doc/CmdList.html +258 -0
- data/doc/CmdRm.html +832 -0
- data/doc/CmdSadd.html +300 -0
- data/doc/CmdSlist.html +258 -0
- data/doc/CmdSrm.html +283 -0
- data/doc/CmdWhich.html +258 -0
- data/doc/EnvVar.html +1351 -0
- data/doc/Rumodule.html +841 -0
- data/doc/RumoduleCommon.html +151 -0
- data/doc/RumoduleMod.html +202 -0
- data/doc/Utility.html +1403 -0
- data/doc/_index.html +202 -0
- data/doc/class_list.html +58 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.CHANGELOG.html +87 -0
- data/doc/file.README.html +303 -0
- data/doc/file_list.html +63 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +303 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +181 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +423 -0
- data/doc/top-level-namespace.html +130 -0
- data/lib/version.rb +6 -0
- data/test/run_fish +3 -0
- data/test/run_zsh_sh_bash +3 -0
- data/test/test_fish +70 -0
- data/test/test_fish.log +60 -0
- data/test/test_golden.log +60 -0
- data/test/test_rumodule.rb +39 -0
- data/test/test_zsh_sh_bash +72 -0
- data/test/test_zsh_sh_bash.log +60 -0
- metadata +110 -0
data/bin/rumodule
ADDED
@@ -0,0 +1,1069 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'como'
|
4
|
+
include Como
|
5
|
+
require_relative '../lib/version'
|
6
|
+
|
7
|
+
|
8
|
+
Spec.command( 'rumodule', 'Tero Isannainen', '2014', [
|
9
|
+
[ :exclusive, 'doc', '-d', "Documentation." ],
|
10
|
+
[ :opt_single, 'shell', '-s', "Shell." ],
|
11
|
+
[ :single, 'command', '-c', "Command." ],
|
12
|
+
[ :opt_multi, 'module', '-m', "Modules to load." ],
|
13
|
+
], {
|
14
|
+
:header => "\n rumodule - Shell env module manager, v#{RumoduleMod.version}\n\n"
|
15
|
+
} )
|
16
|
+
|
17
|
+
|
18
|
+
# Define option combinations.
|
19
|
+
Spec.checkRule do
|
20
|
+
one(
|
21
|
+
'doc',
|
22
|
+
incr( 'command', 'module' ))
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Documentation for Rumodule.
|
27
|
+
if Opt['doc'].given
|
28
|
+
|
29
|
+
puts %q{
|
30
|
+
= Content
|
31
|
+
|
32
|
+
* Introduction
|
33
|
+
* Command Line Usage
|
34
|
+
* Rumodule File Commands
|
35
|
+
* Shell Function
|
36
|
+
* Environment Setup
|
37
|
+
* Summary
|
38
|
+
|
39
|
+
|
40
|
+
= Introduction
|
41
|
+
|
42
|
+
Rumodule is used to manage shell environment variables by
|
43
|
+
adding/removing modules. By adding a module using Rumodule, for
|
44
|
+
example the PATH environment variable can be setup so that the
|
45
|
+
executable is found.
|
46
|
+
|
47
|
+
Modules exist per tool or per tool version. Rumodule makes it easy
|
48
|
+
to maintain and provide tool setups between multiple users.
|
49
|
+
|
50
|
+
The commands are called User Commands. Modules are called Rumodule
|
51
|
+
files and they include Rumodule File Commands.
|
52
|
+
|
53
|
+
Rumodule refers to modules through RUMODULE environment
|
54
|
+
variable. RUMODULE includes a list of directories where Rumodule
|
55
|
+
Files reside.
|
56
|
+
|
57
|
+
Rumodule command is not convenient to be used directly. The user
|
58
|
+
should setup a shell function which is used to utilize Rumodule.
|
59
|
+
Recommended name is "rumo". See: Shell Function.
|
60
|
+
|
61
|
+
Supported shells: zsh, sh, bash, fish
|
62
|
+
|
63
|
+
|
64
|
+
= Command Line Usage
|
65
|
+
|
66
|
+
== Overview
|
67
|
+
|
68
|
+
The most common User Commands are: "add" and "rm". "add" adds
|
69
|
+
modules content to the shell environment and "rm" removes the same
|
70
|
+
content (or its effects).
|
71
|
+
|
72
|
+
Execution examples:
|
73
|
+
rumo add my_module
|
74
|
+
rumo rm my_module
|
75
|
+
|
76
|
+
Other common commands are "list" and "avail". "list" displays a list
|
77
|
+
of loaded modules and "avail" lists all modules found, defined by
|
78
|
+
the RUMODULE env variable.
|
79
|
+
|
80
|
+
|
81
|
+
== List of User Commands
|
82
|
+
|
83
|
+
* add: add (load) one or many modules
|
84
|
+
* sadd: add (load) one or many system modules
|
85
|
+
* rm: remove (unload) one or many modules
|
86
|
+
* srm: remove (unload) one or many system modules
|
87
|
+
* list: list loaded modules
|
88
|
+
* slist: list loaded system modules
|
89
|
+
* which: display module that would be selected from module directory
|
90
|
+
* display: display module content
|
91
|
+
* avail: list all available modules
|
92
|
+
* savail: list all available modules (including system modules)
|
93
|
+
* help: display rumodule commands or module help if module given
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
= Rumodule File Commands
|
98
|
+
|
99
|
+
== Overview
|
100
|
+
|
101
|
+
The Rumodule files include commands to setup a tool for
|
102
|
+
usage. Rumodule files are normal Ruby files, except a set of
|
103
|
+
Rumodule commands are available in the top namespace. The Rumodule
|
104
|
+
File Commands are semantically defined for the "add" command. For
|
105
|
+
"rm" they have the opposite meaning.
|
106
|
+
|
107
|
+
The most common commands are "setenv", "append_path", and
|
108
|
+
"prepend_path".
|
109
|
+
|
110
|
+
"append_path" adds an entry to the end of existing env variable (or
|
111
|
+
new is created). "prepend_path" adds an entry to the beginning of
|
112
|
+
existing env variable. New var is created if it doesn't exist.
|
113
|
+
|
114
|
+
New env variable is created with "setenv" command. Existing env
|
115
|
+
var can be removed with "unsetenv" command.
|
116
|
+
|
117
|
+
Rumodule example:
|
118
|
+
help( "This module is used for tool" )
|
119
|
+
tool_path = ENV['TOOL_PATH']
|
120
|
+
append_path( 'PATH', "#{tool_path}/bin" )
|
121
|
+
add( "tool_setup" )
|
122
|
+
|
123
|
+
|
124
|
+
== List of Rumodule File Commands
|
125
|
+
|
126
|
+
[ setenv( var, value ) ]
|
127
|
+
Set env var "var" to "value".
|
128
|
+
|
129
|
+
[ unsetenv( var ) ]
|
130
|
+
Unset env var "var".
|
131
|
+
|
132
|
+
[ append_path( var, value ) ]
|
133
|
+
Append "value" to env var "var".
|
134
|
+
|
135
|
+
[ prepend_path( var, value ) ]
|
136
|
+
Prepend "value" to env var "var".
|
137
|
+
|
138
|
+
[ remove_path( var, value ) ]
|
139
|
+
Remove "value" from env var "var".
|
140
|
+
|
141
|
+
[ pushenv( var, value ) ]
|
142
|
+
Set env var "var" to "value" and save the old value of "var" for
|
143
|
+
future. When module is removed, the old value is returned.
|
144
|
+
|
145
|
+
[ prereq( mod ) ]
|
146
|
+
Check that module "mod" is loaded, or abort. It is recommended to
|
147
|
+
check for other modules before performing any other operation
|
148
|
+
within the module command. Otherwise the Shell Function should
|
149
|
+
check for "rumodule" return codes, and prevent shell env changes
|
150
|
+
when aborting.
|
151
|
+
|
152
|
+
[ conflict( mod ) ]
|
153
|
+
Check that module "mod" is not loaded, or abort. See "prereq"
|
154
|
+
usage recommendations.
|
155
|
+
|
156
|
+
[ is_loaded( mod ) ]
|
157
|
+
Check if module "mod" is loaded.
|
158
|
+
|
159
|
+
[ add( mod ) ]
|
160
|
+
Add a module "mod" from Rumodule file.
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
= Shell Function
|
165
|
+
|
166
|
+
== Overview
|
167
|
+
|
168
|
+
Rumodule user must setup a shell function to use Rumodule
|
169
|
+
easily. Recommended name for the function is "rumo". The purpose of
|
170
|
+
the function is to map user arguments to "rumodule" command and pass
|
171
|
+
"rumodule" output to shell for evaluation. This enables the user
|
172
|
+
command to change the shell environment variable contents.
|
173
|
+
|
174
|
+
NOTE: If you are using a Ruby version which takes a long time to
|
175
|
+
load into memory, please consider referencing directly into suitable
|
176
|
+
Ruby version in "rumo".
|
177
|
+
|
178
|
+
|
179
|
+
== Shell Function examples
|
180
|
+
|
181
|
+
Setup "rumo" command for sh, zsh, or bash shells:
|
182
|
+
rumo () {
|
183
|
+
cmd=$1
|
184
|
+
shift
|
185
|
+
if test $# -gt 0; then
|
186
|
+
eval `rumodule -s zsh -c $cmd -m $*`
|
187
|
+
else
|
188
|
+
eval `rumodule -c $cmd`
|
189
|
+
fi
|
190
|
+
}
|
191
|
+
|
192
|
+
Setup "rumo" command for fish shell:
|
193
|
+
function rumo
|
194
|
+
if test (count $argv) -gt 1
|
195
|
+
set cmd (rumodule -s fish -c $argv[1] -m $argv[2..-1])
|
196
|
+
else
|
197
|
+
set cmd (rumodule -s fish -c $argv[1])
|
198
|
+
end
|
199
|
+
eval $cmd
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
= Environment Setup
|
204
|
+
|
205
|
+
Rumodule requires the RUMODULE env var to be set to the root
|
206
|
+
directory or directories where the Rumodule Files reside.
|
207
|
+
|
208
|
+
Lets assume the "$HOME/usr/share/rumodule" directory is used to
|
209
|
+
store the modules.
|
210
|
+
|
211
|
+
The directory content could be the following:
|
212
|
+
tool1
|
213
|
+
tool2
|
214
|
+
tool3/1.2.3
|
215
|
+
/1.2.6
|
216
|
+
tool4
|
217
|
+
system-
|
218
|
+
|
219
|
+
"tool1,2,4" are module files and "tool3" is a subdirectory including
|
220
|
+
module files "1.2.3" and "1.2.6". "system-" is a system module file,
|
221
|
+
which is visible only with "savail" command. System module files are
|
222
|
+
used to separate between compulsory module files vs user selectable.
|
223
|
+
|
224
|
+
"tool3" has two versions and it could be referred for example with:
|
225
|
+
rumo add tool3
|
226
|
+
rumo add tool3/1.2.6
|
227
|
+
|
228
|
+
If version is left out, Rumodule uses one of the version. The
|
229
|
+
selection is performed by first sorting the directory entries and
|
230
|
+
then selecting the last.
|
231
|
+
|
232
|
+
Usually the user should specify the actual version requested when
|
233
|
+
adding the module and when removing the directory is enough.
|
234
|
+
|
235
|
+
Rumodule files can be hidden from the system by using the "." prefix
|
236
|
+
to filename (as for "ls" shell utility").
|
237
|
+
|
238
|
+
|
239
|
+
= Summary
|
240
|
+
|
241
|
+
These steps are required to take Rumodule into use:
|
242
|
+
|
243
|
+
* Create Rumodule Files to dir.
|
244
|
+
* Set RUMODULE env var to dir.
|
245
|
+
* Setup rumo Shell Function.
|
246
|
+
|
247
|
+
}
|
248
|
+
|
249
|
+
# ' Fix ruby-mode coloring
|
250
|
+
|
251
|
+
exit( false )
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
# Check for working environment:
|
256
|
+
if ENV['RUMODULE'] == nil
|
257
|
+
STDERR.puts " User must define \"RUMODULE\" environment variable...\n See: rumodule -d"
|
258
|
+
exit( false )
|
259
|
+
end
|
260
|
+
|
261
|
+
|
262
|
+
# "home"-method.
|
263
|
+
module RumoduleMod
|
264
|
+
|
265
|
+
# Return home path.
|
266
|
+
def home
|
267
|
+
ENV['HOME']
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
include RumoduleMod
|
273
|
+
|
274
|
+
|
275
|
+
class RumoduleCommon
|
276
|
+
|
277
|
+
include RumoduleMod
|
278
|
+
|
279
|
+
# Shell constant.
|
280
|
+
if Opt['shell'].given
|
281
|
+
SHELL = Opt['shell'].value
|
282
|
+
else
|
283
|
+
SHELL = 'zsh'
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
|
290
|
+
# Environment variable that has been read from "unix" env.
|
291
|
+
class EnvVar < RumoduleCommon
|
292
|
+
|
293
|
+
# Variable name.
|
294
|
+
attr_reader :name
|
295
|
+
|
296
|
+
# Dirty flag indicates that the env has to be updated.
|
297
|
+
attr_reader :dirty
|
298
|
+
|
299
|
+
# EnvVar value.
|
300
|
+
attr_reader :value
|
301
|
+
|
302
|
+
|
303
|
+
# Check for "unix" var existance.
|
304
|
+
#
|
305
|
+
# @param name [String] Env var name to check.
|
306
|
+
# @return [String] Value or nil.
|
307
|
+
def EnvVar.exist?( name )
|
308
|
+
ENV[name]
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
# Initialize name, dirty and unset. If unset is true, then "unset"
|
313
|
+
# command is output to shell.
|
314
|
+
#
|
315
|
+
# @param name [String] Env var name.
|
316
|
+
# @param value [String] Value for Env var.
|
317
|
+
def initialize( name, value = nil )
|
318
|
+
@name = name
|
319
|
+
@dirty = false
|
320
|
+
@unset = false
|
321
|
+
if value
|
322
|
+
@value = value
|
323
|
+
else
|
324
|
+
@value = ENV[name].split(':')
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
# Set variable to a value.
|
330
|
+
#
|
331
|
+
# @param value [String] Value for Env var.
|
332
|
+
def set( value )
|
333
|
+
@dirty = true
|
334
|
+
@unset = false
|
335
|
+
@value = [ value ]
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# Unset variable from env.
|
340
|
+
def unset
|
341
|
+
@dirty = true
|
342
|
+
@unset = true
|
343
|
+
@value = []
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
# Place new value infront of the path.
|
348
|
+
#
|
349
|
+
# @param value [String] Value for Env var.
|
350
|
+
def prepend_path( value )
|
351
|
+
@dirty = true
|
352
|
+
@unset = false
|
353
|
+
@value.unshift( value )
|
354
|
+
end
|
355
|
+
|
356
|
+
|
357
|
+
# Place new value at end of the path.
|
358
|
+
#
|
359
|
+
# @param value [String] Value for Env var.
|
360
|
+
def append_path( value )
|
361
|
+
@dirty = true
|
362
|
+
@unset = false
|
363
|
+
@value.push( value )
|
364
|
+
end
|
365
|
+
|
366
|
+
|
367
|
+
# Remove value from the path.
|
368
|
+
#
|
369
|
+
# @param value [String] Value to remove from Env var.
|
370
|
+
def remove_path( value )
|
371
|
+
@dirty = true
|
372
|
+
@unset = false
|
373
|
+
@value.delete( value )
|
374
|
+
end
|
375
|
+
|
376
|
+
|
377
|
+
# Remove value at index.
|
378
|
+
#
|
379
|
+
# @param idx [Integer] Value index used to remove from Env var.
|
380
|
+
def delete_index( idx )
|
381
|
+
@dirty = true
|
382
|
+
@unset = false
|
383
|
+
@value.delete_at( idx )
|
384
|
+
end
|
385
|
+
|
386
|
+
|
387
|
+
# Entries in Env var.
|
388
|
+
#
|
389
|
+
# @return [Integer] Length.
|
390
|
+
def length
|
391
|
+
@value.length
|
392
|
+
end
|
393
|
+
|
394
|
+
|
395
|
+
# Format EnvVar for shell. Output depends on whether the EnvVar
|
396
|
+
# has been "unset" or not.
|
397
|
+
#
|
398
|
+
# @return [String] Shell's eval command arguments.
|
399
|
+
def export
|
400
|
+
if @unset
|
401
|
+
case SHELL
|
402
|
+
when 'zsh', 'sh', 'bash'; "unset #{name}"
|
403
|
+
when 'fish'; "set -e #{name}"
|
404
|
+
else raise "Unknown shell: \"#{SHELL}\""
|
405
|
+
end
|
406
|
+
else
|
407
|
+
case SHELL
|
408
|
+
when 'zsh', 'sh', 'bash'; "export #{name}=#{@value.join(':')}"
|
409
|
+
# when 'fish'; "export #{name} #{@value.join(' ')}"
|
410
|
+
when 'fish'; "set -gx #{name} #{@value.join(' ')}"
|
411
|
+
else raise "Unknown shell: \"#{SHELL}\""
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
# Utility routines for Rumodule internal functions.
|
420
|
+
module Utility
|
421
|
+
|
422
|
+
# List of loaded modules.
|
423
|
+
LOADED = 'RUMODULE_LOADED'
|
424
|
+
|
425
|
+
# List of loaded system modules.
|
426
|
+
SYSLOADED = 'RUMODULE_SYSLOADED'
|
427
|
+
|
428
|
+
# List of loaded submodules.
|
429
|
+
SUBLOADED = 'RUMODULE_SUBLOADED'
|
430
|
+
|
431
|
+
# List of directories including modules.
|
432
|
+
MODULEDIRS = ENV['RUMODULE'] ? ENV['RUMODULE'].split(':') : []
|
433
|
+
|
434
|
+
# Stack to store pushed env vars.
|
435
|
+
RUMODULE_PUSH = 'RUMODULE_PUSH'
|
436
|
+
|
437
|
+
|
438
|
+
|
439
|
+
# List of loaded modules.
|
440
|
+
#
|
441
|
+
# @return [Array<String>] Loaded modules.
|
442
|
+
def loaded
|
443
|
+
getenvar( LOADED, true ).value
|
444
|
+
end
|
445
|
+
|
446
|
+
|
447
|
+
# List of loaded system modules.
|
448
|
+
#
|
449
|
+
# @return [Array<String>] Loaded modules.
|
450
|
+
def sys_loaded
|
451
|
+
getenvar( SYSLOADED, true ).value
|
452
|
+
end
|
453
|
+
|
454
|
+
|
455
|
+
# List of loaded modules (normal + system).
|
456
|
+
#
|
457
|
+
# @return [Array<String>] Loaded modules.
|
458
|
+
def all_loaded
|
459
|
+
getenvar( LOADED, true ).value +
|
460
|
+
getenvar( SYSLOADED, true ).value +
|
461
|
+
getenvar( SUBLOADED, true ).value
|
462
|
+
end
|
463
|
+
|
464
|
+
|
465
|
+
# Report usage info.
|
466
|
+
def usage( msg )
|
467
|
+
STDERR.puts( msg )
|
468
|
+
abort
|
469
|
+
end
|
470
|
+
|
471
|
+
|
472
|
+
# Report error.
|
473
|
+
def error( msg )
|
474
|
+
STDERR.puts( "rumodule error: #{msg}" )
|
475
|
+
abort
|
476
|
+
end
|
477
|
+
|
478
|
+
|
479
|
+
# Report warning.
|
480
|
+
def warning( msg )
|
481
|
+
STDERR.puts( "rumodule warning: #{msg}" )
|
482
|
+
abort
|
483
|
+
end
|
484
|
+
|
485
|
+
|
486
|
+
# Exit program without shell output.
|
487
|
+
def abort
|
488
|
+
STDERR.flush
|
489
|
+
exit( false )
|
490
|
+
end
|
491
|
+
|
492
|
+
|
493
|
+
# Return module file. If argument is dir, then check for directory
|
494
|
+
# content for modules.
|
495
|
+
#
|
496
|
+
# Alternatively 'm' can be abspath to module.
|
497
|
+
#
|
498
|
+
# @param m [String] Module name hint.
|
499
|
+
# @return [String] Path to module.
|
500
|
+
def findModule( m )
|
501
|
+
|
502
|
+
if m[0] == '/'
|
503
|
+
|
504
|
+
# Abspath
|
505
|
+
m
|
506
|
+
|
507
|
+
else
|
508
|
+
|
509
|
+
# Search for module.
|
510
|
+
|
511
|
+
pwd = Dir.pwd
|
512
|
+
|
513
|
+
ret = nil
|
514
|
+
|
515
|
+
MODULEDIRS.each do |mdir|
|
516
|
+
|
517
|
+
Dir.chdir mdir
|
518
|
+
|
519
|
+
if File.directory?( m )
|
520
|
+
ret = Dir[ "#{m}/*" ].sort[-1]
|
521
|
+
elsif File.exist?( m )
|
522
|
+
ret = m
|
523
|
+
end
|
524
|
+
|
525
|
+
if ret
|
526
|
+
ret = mdir + "/" + ret
|
527
|
+
break
|
528
|
+
end
|
529
|
+
|
530
|
+
end
|
531
|
+
|
532
|
+
Dir.chdir( pwd )
|
533
|
+
|
534
|
+
ret
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
|
539
|
+
# Load module content.
|
540
|
+
#
|
541
|
+
# @param m [String] Module name hint.
|
542
|
+
def loadModule( m )
|
543
|
+
path = findModule( m )
|
544
|
+
if path && File.exist?( path )
|
545
|
+
instance_eval( IO::read( path ), path )
|
546
|
+
path
|
547
|
+
else
|
548
|
+
error "Unknown module: \"#{m}\"!"
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
|
553
|
+
# Register module as loaded.
|
554
|
+
#
|
555
|
+
# @param m [String] Module path.
|
556
|
+
def registerModule( m, list = :normal )
|
557
|
+
case list
|
558
|
+
when :normal; getenvar( LOADED, true ).append_path( m )
|
559
|
+
when :system; getenvar( SYSLOADED, true ).append_path( m )
|
560
|
+
when :sub; getenvar( SUBLOADED, true ).append_path( m )
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
|
565
|
+
# UnRegister module as loaded.
|
566
|
+
#
|
567
|
+
# @param m [String] Module path.
|
568
|
+
def unregisterModule( m, list = :normal )
|
569
|
+
|
570
|
+
case list
|
571
|
+
when :normal; loaded = getenvar( LOADED )
|
572
|
+
when :system; loaded = getenvar( SYSLOADED )
|
573
|
+
when :sub; loaded = getenvar( SUBLOADED )
|
574
|
+
end
|
575
|
+
|
576
|
+
# loaded = getenvar( LOADED )
|
577
|
+
index = loaded.value.index( m )
|
578
|
+
|
579
|
+
if index
|
580
|
+
|
581
|
+
# Accurate match.
|
582
|
+
loaded.delete_index( index )
|
583
|
+
|
584
|
+
else
|
585
|
+
|
586
|
+
# Regexp match.
|
587
|
+
loaded.length.times do |i|
|
588
|
+
if Regexp.new( "#{m}/" ).match( loaded.value[i] )
|
589
|
+
loaded.delete_index( i )
|
590
|
+
return
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
end
|
595
|
+
|
596
|
+
end
|
597
|
+
|
598
|
+
|
599
|
+
# Rumodule help.
|
600
|
+
def commonHelp
|
601
|
+
usage %Q{
|
602
|
+
Available Commands and Args:
|
603
|
+
- add modulefile+
|
604
|
+
- sadd modulefile+
|
605
|
+
- rm modulefile+
|
606
|
+
- list
|
607
|
+
- slist
|
608
|
+
- which modulefile
|
609
|
+
- display modulefile
|
610
|
+
- avail
|
611
|
+
- savail
|
612
|
+
- help modulefile
|
613
|
+
|
614
|
+
}
|
615
|
+
end
|
616
|
+
|
617
|
+
|
618
|
+
# Empty help for modules. Help gets defined in CmdHelp when help
|
619
|
+
# is requested by user.
|
620
|
+
def help( str )
|
621
|
+
true
|
622
|
+
end
|
623
|
+
|
624
|
+
end
|
625
|
+
|
626
|
+
|
627
|
+
# Prefined Rumodule commands.
|
628
|
+
class Rumodule < RumoduleCommon
|
629
|
+
|
630
|
+
include Utility
|
631
|
+
|
632
|
+
|
633
|
+
# Map rumodule cmd to internal class method.
|
634
|
+
#
|
635
|
+
# @param cmd [String] Rumodule user command.
|
636
|
+
# @param mods [Array] List of modules.
|
637
|
+
def Rumodule.run( cmd, mods )
|
638
|
+
|
639
|
+
# Internal class name.
|
640
|
+
cmdClass = "Cmd#{cmd.capitalize}"
|
641
|
+
|
642
|
+
if Module.const_defined?( cmdClass )
|
643
|
+
|
644
|
+
# Create instance of the class.
|
645
|
+
obj = Object::const_get( cmdClass ).new
|
646
|
+
|
647
|
+
# Execute rumodule method.
|
648
|
+
obj.action( mods )
|
649
|
+
|
650
|
+
else
|
651
|
+
|
652
|
+
error "Unknown command: \"#{cmd}\"!"
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
|
657
|
+
# List of output command lines to shell. Must be separeted
|
658
|
+
# with semicolon and newline.
|
659
|
+
@@outputlist = []
|
660
|
+
|
661
|
+
|
662
|
+
# Cache variables from env to Hash. All updated values are visible
|
663
|
+
# to subsequent commands.
|
664
|
+
@@varcache = {}
|
665
|
+
|
666
|
+
|
667
|
+
# Fetch env varible from env. Conditionally create the env var.
|
668
|
+
#
|
669
|
+
# @param var [String] Env var name.
|
670
|
+
# @param create [Boolean] Create if not existing.
|
671
|
+
# @return [String] Env var value.
|
672
|
+
def getenvar( var, create = false )
|
673
|
+
|
674
|
+
if @@varcache[ var ]
|
675
|
+
# In cache.
|
676
|
+
@@varcache[ var ]
|
677
|
+
else
|
678
|
+
|
679
|
+
# Not in cache.
|
680
|
+
if ENV[ var ]
|
681
|
+
|
682
|
+
# In env.
|
683
|
+
v = EnvVar.new( var )
|
684
|
+
@@varcache[ var ] = v
|
685
|
+
|
686
|
+
elsif create
|
687
|
+
|
688
|
+
# Create as new.
|
689
|
+
v = EnvVar.new( var, [] )
|
690
|
+
@@varcache[ var ] = v
|
691
|
+
|
692
|
+
else
|
693
|
+
nil
|
694
|
+
end
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
|
699
|
+
# Is module(s) loaded?
|
700
|
+
#
|
701
|
+
# @param mod [String] Module name.
|
702
|
+
# @return [Boolean] True if loaded.
|
703
|
+
def _is_loaded( mod )
|
704
|
+
mod = [ mod ] if mod.class != Array
|
705
|
+
|
706
|
+
mod.each do |i|
|
707
|
+
if all_loaded.index( i )
|
708
|
+
return true
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
false
|
713
|
+
end
|
714
|
+
|
715
|
+
|
716
|
+
# Place str to output buffer (shell output).
|
717
|
+
#
|
718
|
+
# @param str [String] String for output.
|
719
|
+
def _output( str )
|
720
|
+
@@outputlist.push str
|
721
|
+
end
|
722
|
+
|
723
|
+
|
724
|
+
# Flush all pending shell output.
|
725
|
+
def Rumodule.flush
|
726
|
+
|
727
|
+
# Check for changed env varibles and perform update.
|
728
|
+
@@varcache.values.each do |v|
|
729
|
+
if v.dirty
|
730
|
+
@@outputlist.push v.export
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
# Output updates.
|
735
|
+
if @@outputlist.length > 0
|
736
|
+
puts @@outputlist.join( ";\n" )
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
740
|
+
end
|
741
|
+
|
742
|
+
|
743
|
+
|
744
|
+
# Help command.
|
745
|
+
class CmdHelp < Rumodule
|
746
|
+
|
747
|
+
def action( mod = nil )
|
748
|
+
|
749
|
+
if mod
|
750
|
+
|
751
|
+
begin
|
752
|
+
|
753
|
+
# Override dummy help method.
|
754
|
+
self.class.send( :define_method, :help, lambda { |str|
|
755
|
+
usage( str )
|
756
|
+
} )
|
757
|
+
|
758
|
+
loadModule( mod )
|
759
|
+
|
760
|
+
rescue
|
761
|
+
|
762
|
+
STDERR.puts "No help provided!"
|
763
|
+
|
764
|
+
end
|
765
|
+
|
766
|
+
|
767
|
+
else
|
768
|
+
|
769
|
+
commonHelp
|
770
|
+
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
end
|
775
|
+
|
776
|
+
|
777
|
+
# Display command.
|
778
|
+
class CmdDisplay < Rumodule
|
779
|
+
|
780
|
+
def action( mod )
|
781
|
+
mod = findModule( mod )
|
782
|
+
usage File.readlines( mod )
|
783
|
+
end
|
784
|
+
|
785
|
+
end
|
786
|
+
|
787
|
+
|
788
|
+
# Which command.
|
789
|
+
class CmdWhich < Rumodule
|
790
|
+
|
791
|
+
def action( mod )
|
792
|
+
usage findModule( mod )
|
793
|
+
end
|
794
|
+
|
795
|
+
end
|
796
|
+
|
797
|
+
|
798
|
+
# List command.
|
799
|
+
class CmdList < Rumodule
|
800
|
+
|
801
|
+
def action( mod = nil )
|
802
|
+
usage loaded
|
803
|
+
end
|
804
|
+
|
805
|
+
end
|
806
|
+
|
807
|
+
|
808
|
+
# List command.
|
809
|
+
class CmdSlist < Rumodule
|
810
|
+
|
811
|
+
def action( mod = nil )
|
812
|
+
usage sys_loaded
|
813
|
+
end
|
814
|
+
|
815
|
+
end
|
816
|
+
|
817
|
+
|
818
|
+
# Add command.
|
819
|
+
class CmdAdd < Rumodule
|
820
|
+
|
821
|
+
# Add modules if not loaded yet.
|
822
|
+
def action( mods, list = :normal )
|
823
|
+
mods.each do |mod|
|
824
|
+
mod_path = findModule( mod )
|
825
|
+
if mod_path == nil
|
826
|
+
error "Unknown module: \"#{mod}\"..."
|
827
|
+
elsif !_is_loaded( mod_path )
|
828
|
+
loaded_mod = loadModule( mod_path )
|
829
|
+
registerModule( loaded_mod, list )
|
830
|
+
else
|
831
|
+
warning( "Module is already loaded: \"#{mod_path}\"..." )
|
832
|
+
end
|
833
|
+
end
|
834
|
+
end
|
835
|
+
|
836
|
+
|
837
|
+
# ------------------------------------------------------------
|
838
|
+
# Module file commands:
|
839
|
+
|
840
|
+
|
841
|
+
def setenv( var, value )
|
842
|
+
getenvar( var, true ).set( value )
|
843
|
+
end
|
844
|
+
|
845
|
+
|
846
|
+
def unsetenv( var, value = nil )
|
847
|
+
if v = getenvar( var )
|
848
|
+
v.unset
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
|
853
|
+
def append_path( var, value )
|
854
|
+
getenvar( var, true ).append_path( value )
|
855
|
+
end
|
856
|
+
|
857
|
+
|
858
|
+
def prepend_path( var, value )
|
859
|
+
getenvar( var, true ).prepend_path( value )
|
860
|
+
end
|
861
|
+
|
862
|
+
|
863
|
+
def remove_path( var, value )
|
864
|
+
getenvar( var, true ).remove_path( value )
|
865
|
+
end
|
866
|
+
|
867
|
+
|
868
|
+
def pushenv( var, value )
|
869
|
+
# Store old value if it exists.
|
870
|
+
bup = "#{RUMODULE_PUSH}_#{var}"
|
871
|
+
if EnvVar.exist?( var )
|
872
|
+
getenvar( bup, true ).prepend_path( ENV[var] )
|
873
|
+
end
|
874
|
+
getenvar( var, true ).set( value )
|
875
|
+
end
|
876
|
+
|
877
|
+
|
878
|
+
def prereq( mod )
|
879
|
+
unless is_loaded( mod )
|
880
|
+
usage "Prerequisite module not loaded: #{mod}"
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
884
|
+
|
885
|
+
def conflict( mod )
|
886
|
+
if is_loaded( mod )
|
887
|
+
usage "Conflicting module loaded: #{mod}"
|
888
|
+
end
|
889
|
+
end
|
890
|
+
|
891
|
+
|
892
|
+
def is_loaded( mod )
|
893
|
+
_is_loaded( findModule( mod ) )
|
894
|
+
end
|
895
|
+
|
896
|
+
|
897
|
+
def add( mod )
|
898
|
+
action( [ mod ], :sub )
|
899
|
+
end
|
900
|
+
|
901
|
+
end
|
902
|
+
|
903
|
+
|
904
|
+
# System add command.
|
905
|
+
class CmdSadd < CmdAdd
|
906
|
+
|
907
|
+
# Add modules if not loaded yet.
|
908
|
+
def action( mods, list = :system )
|
909
|
+
mods.each do |mod|
|
910
|
+
mod_path = findModule( mod )
|
911
|
+
if mod_path == nil
|
912
|
+
error "Unknown module: \"#{mod}\"..."
|
913
|
+
elsif !_is_loaded( mod_path )
|
914
|
+
loaded_mod = loadModule( mod_path )
|
915
|
+
registerModule( loaded_mod, list )
|
916
|
+
end
|
917
|
+
end
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
|
922
|
+
# Rm command.
|
923
|
+
class CmdRm < Rumodule
|
924
|
+
|
925
|
+
def action( mods, list = :normal )
|
926
|
+
mods.each do |mod|
|
927
|
+
mod_path = findModule( mod )
|
928
|
+
if _is_loaded( mod_path )
|
929
|
+
loaded_mod = loadModule( mod_path )
|
930
|
+
unregisterModule( loaded_mod, list )
|
931
|
+
end
|
932
|
+
end
|
933
|
+
end
|
934
|
+
|
935
|
+
|
936
|
+
# ------------------------------------------------------------
|
937
|
+
# Module file commands:
|
938
|
+
|
939
|
+
def setenv( var, value )
|
940
|
+
if v = getenvar( var )
|
941
|
+
v.unset
|
942
|
+
end
|
943
|
+
end
|
944
|
+
|
945
|
+
def unsetenv( var, value = nil )
|
946
|
+
if value
|
947
|
+
getenvar( var, true ).set( value )
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
951
|
+
def append_path( var, value )
|
952
|
+
getenvar( var ).remove_path( value )
|
953
|
+
end
|
954
|
+
|
955
|
+
def prepend_path( var, value )
|
956
|
+
getenvar( var ).remove_path( value )
|
957
|
+
end
|
958
|
+
|
959
|
+
def remove_path( var, value )
|
960
|
+
getenvar( var, true ).prepend_path( value )
|
961
|
+
end
|
962
|
+
|
963
|
+
def pushenv( var, value )
|
964
|
+
|
965
|
+
# Store old value if it exists.
|
966
|
+
bup = "#{RUMODULE_PUSH}_#{var}"
|
967
|
+
|
968
|
+
if EnvVar.exist?( bup )
|
969
|
+
v = getenvar( bup )
|
970
|
+
getenvar( var, true ).set( v.value[0] )
|
971
|
+
v.value.shift
|
972
|
+
end
|
973
|
+
end
|
974
|
+
|
975
|
+
def prereq( mod )
|
976
|
+
true
|
977
|
+
end
|
978
|
+
|
979
|
+
def conflict( mod )
|
980
|
+
true
|
981
|
+
end
|
982
|
+
|
983
|
+
def is_loaded( mod )
|
984
|
+
true
|
985
|
+
end
|
986
|
+
|
987
|
+
def add( mod )
|
988
|
+
action( [ mod ], :sub )
|
989
|
+
end
|
990
|
+
|
991
|
+
end
|
992
|
+
|
993
|
+
|
994
|
+
# Rm system command.
|
995
|
+
class CmdSrm < CmdRm
|
996
|
+
|
997
|
+
def action( mods, list = :system )
|
998
|
+
mods.each do |mod|
|
999
|
+
mod_path = findModule( mod )
|
1000
|
+
if _is_loaded( mod_path )
|
1001
|
+
loaded_mod = loadModule( mod_path )
|
1002
|
+
unregisterModule( loaded_mod, list )
|
1003
|
+
end
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
|
1009
|
+
|
1010
|
+
# Get command line options.
|
1011
|
+
|
1012
|
+
cmd = Opt['command'].value
|
1013
|
+
|
1014
|
+
mod = mods = nil
|
1015
|
+
if Opt['module'].given
|
1016
|
+
mod = Opt['module'].value[0]
|
1017
|
+
mods = Opt['module'].value
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
|
1021
|
+
# Select the command.
|
1022
|
+
|
1023
|
+
case cmd
|
1024
|
+
|
1025
|
+
when 'help'
|
1026
|
+
Rumodule.run( cmd, mod )
|
1027
|
+
|
1028
|
+
when 'avail'
|
1029
|
+
Utility::MODULEDIRS.each do |mdir|
|
1030
|
+
STDERR.puts( Dir["#{mdir}/**/*"].select do |i| i[-1] != "-" end )
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
when 'savail'
|
1034
|
+
Utility::MODULEDIRS.each do |mdir|
|
1035
|
+
STDERR.puts( Dir["#{mdir}/**/*"] )
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
when 'display'
|
1039
|
+
Rumodule.run( cmd, mod )
|
1040
|
+
|
1041
|
+
when 'which'
|
1042
|
+
Rumodule.run( cmd, mod )
|
1043
|
+
|
1044
|
+
when 'list'
|
1045
|
+
Rumodule.run( cmd, mod )
|
1046
|
+
|
1047
|
+
when 'slist'
|
1048
|
+
Rumodule.run( cmd, mod )
|
1049
|
+
|
1050
|
+
when 'add'
|
1051
|
+
Rumodule.run( cmd, mods )
|
1052
|
+
|
1053
|
+
when 'sadd'
|
1054
|
+
Rumodule.run( cmd, mods )
|
1055
|
+
|
1056
|
+
when 'rm'
|
1057
|
+
Rumodule.run( cmd, mods )
|
1058
|
+
|
1059
|
+
when 'srm'
|
1060
|
+
Rumodule.run( cmd, mods )
|
1061
|
+
|
1062
|
+
else
|
1063
|
+
error "Unknown command: \"#{cmd}\"!"
|
1064
|
+
|
1065
|
+
end
|
1066
|
+
|
1067
|
+
|
1068
|
+
# Flush command updates.
|
1069
|
+
Rumodule.flush
|