workEnv 0.1.0
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/LICENSE +620 -0
- data/bin/wenv +10 -0
- data/lib/WorkEnvs/Action.rb +604 -0
- data/lib/WorkEnvs/Common/Arch.rb +185 -0
- data/lib/WorkEnvs/Common/Config.rb +364 -0
- data/lib/WorkEnvs/Common/Confirm.rb +80 -0
- data/lib/WorkEnvs/Common/DBInterface.rb +608 -0
- data/lib/WorkEnvs/Common/Defines.rb +20 -0
- data/lib/WorkEnvs/Common/Dependencies.rb +206 -0
- data/lib/WorkEnvs/Common/EnvOpts.rb +129 -0
- data/lib/WorkEnvs/Common/Package.rb +116 -0
- data/lib/WorkEnvs/Common/PackageDownloader.rb +760 -0
- data/lib/WorkEnvs/Common/VersionSelector.rb +278 -0
- data/lib/WorkEnvs/Common.rb +10 -0
- data/lib/WorkEnvs/Core.rb +1004 -0
- data/lib/WorkEnvs/Envs/Any.rb +49 -0
- data/lib/WorkEnvs/Envs/Basic.rb +204 -0
- data/lib/WorkEnvs/accessors.rb +147 -0
- data/lib/WorkEnvs/global.rb +749 -0
- data/lib/WorkEnvs.rb +75 -0
- data/workrc-completion.sh +284 -0
- metadata +65 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
module WorkEnvs
|
|
3
|
+
# Class to store all the dependencies of an env
|
|
4
|
+
#
|
|
5
|
+
# It provides helpers to convert between version names and sha1
|
|
6
|
+
#
|
|
7
|
+
# Dependencies can come from multiple sources
|
|
8
|
+
# - rev_files
|
|
9
|
+
# - --sha1, --sub-sha1 options
|
|
10
|
+
# - --version option
|
|
11
|
+
# - Package (RPM, Deb) dependencies
|
|
12
|
+
#
|
|
13
|
+
# Dependencies from env to its version (and its subEnv versions) are stored
|
|
14
|
+
# as depInfo hash:
|
|
15
|
+
#
|
|
16
|
+
# { :sha1 => <sha1>, :version => <version> }
|
|
17
|
+
class Dependencies
|
|
18
|
+
# Mark the environment as partial. (default = false)
|
|
19
|
+
#
|
|
20
|
+
# It means that it is OK for some environment class
|
|
21
|
+
# from the env dependency tree to not have any dep_info to them
|
|
22
|
+
attr_accessor :partialEnv
|
|
23
|
+
|
|
24
|
+
# Flag enable by setting WENV_IGNORE_CONFLICTS (default = nil)
|
|
25
|
+
#
|
|
26
|
+
# Ignore if a dep_info is pushed to an envClass is different from
|
|
27
|
+
# a previous dep_info pushed for the same envClass
|
|
28
|
+
# In this case, the first on is kept.
|
|
29
|
+
#
|
|
30
|
+
# SEROUSLY DANGEROUS ! DON'T USE IT UNLESS YOU KNOW WHAT YOU'RE DOING !!!
|
|
31
|
+
attr_reader :ignore_conflicts
|
|
32
|
+
|
|
33
|
+
# Pointer to a PackageDownloader used to convert version and SHA1 (default = nil)
|
|
34
|
+
attr_accessor :downloader
|
|
35
|
+
|
|
36
|
+
# Hash of dep_infos (default = {})
|
|
37
|
+
attr_reader :deps
|
|
38
|
+
|
|
39
|
+
# Array of fields to query in the package DB
|
|
40
|
+
FIELDS = [ :sha1, :version ]
|
|
41
|
+
|
|
42
|
+
# Default constructor
|
|
43
|
+
def initialize
|
|
44
|
+
@deps = {}
|
|
45
|
+
@partialEnv = false
|
|
46
|
+
@ignore_conflicts = nil
|
|
47
|
+
@ignore_conflicts = true if ENV["WENV_IGNORE_CONFLICTS"].to_s != ""
|
|
48
|
+
@downloader = nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Internal function to add a dependency to deps
|
|
52
|
+
#
|
|
53
|
+
# - env is either the envType or an envClass
|
|
54
|
+
# - dInfos is a dep_info hash generated by PackageDownloader
|
|
55
|
+
#
|
|
56
|
+
# Returns:
|
|
57
|
+
# - true on success
|
|
58
|
+
# - false on failure if @ignore_conflicts == true
|
|
59
|
+
# Throws an exception on failure if @ignore_conflicts != true
|
|
60
|
+
def _push(env, dInfos)
|
|
61
|
+
name = (env.kind_of? Symbol) ? env : WorkEnvs::getEnvType(env)
|
|
62
|
+
|
|
63
|
+
WorkEnvs::dputs("Deps[#{name}] <= (#{dInfos.to_s})")
|
|
64
|
+
|
|
65
|
+
FIELDS.each(){|f|
|
|
66
|
+
raise("Incomplete dependency #{dInfos}. '#{f.to_s}' field is missing") if dInfos[f] == nil
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if @deps[name] != nil then
|
|
70
|
+
if @deps[name] != dInfos then
|
|
71
|
+
return false if @ignore_conflicts == true
|
|
72
|
+
|
|
73
|
+
raise("Invalid dependencies for #{name}.\nRequire for #{name.to_s} both:\n"+
|
|
74
|
+
"\t* '#{@deps[name].to_s}'\n\t* '#{dInfos.to_s}' ")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
@deps[name] = dInfos
|
|
78
|
+
return true
|
|
79
|
+
end
|
|
80
|
+
private :_push
|
|
81
|
+
|
|
82
|
+
# Convert an (envType, sha1) couple to a dep_info and add it to deps using #_push
|
|
83
|
+
#
|
|
84
|
+
# env is either the envType or an envClass
|
|
85
|
+
#
|
|
86
|
+
# Return _push result or false if required == false and no matching SHA1 was found
|
|
87
|
+
# in the DB
|
|
88
|
+
#
|
|
89
|
+
# Throws EmptyQueryException if required == true and no match was found
|
|
90
|
+
def push_sha1(env, sha1, required = true)
|
|
91
|
+
return false if sha1.to_s == ""
|
|
92
|
+
#SHA1 but no version
|
|
93
|
+
dInfos = @downloader.queryDepInfosFromSHA1(env, sha1, required)
|
|
94
|
+
return false if dInfos == nil
|
|
95
|
+
return _push(env, dInfos)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Convert an (envType, version) couple to a dep_info and add it to deps using #_push
|
|
99
|
+
#
|
|
100
|
+
# env is either the envType or an envClass
|
|
101
|
+
#
|
|
102
|
+
# Return _push result or false if required == false and no matching version was found
|
|
103
|
+
# in the DB
|
|
104
|
+
#
|
|
105
|
+
# Throws EmptyQueryException if required == true and no match was found
|
|
106
|
+
def push_version(env, version, required = true)
|
|
107
|
+
return false if version.to_s == ""
|
|
108
|
+
|
|
109
|
+
#SHA1 but no version
|
|
110
|
+
dInfos = @downloader.queryDepInfosFromVersion(env, version, required)
|
|
111
|
+
return false if dInfos == nil
|
|
112
|
+
return _push(env, dInfos)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Convert an (envType, package full name) couple to a dep_info and add it to deps using #_push
|
|
116
|
+
#
|
|
117
|
+
# env is either the envType or an envClass
|
|
118
|
+
#
|
|
119
|
+
# Return _push result or false if required == false and no matching package was found
|
|
120
|
+
# in the DB
|
|
121
|
+
#
|
|
122
|
+
# Throws EmptyQueryException if required == true and no match was found
|
|
123
|
+
def push_name(env, pName, required = true)
|
|
124
|
+
dInfos = @downloader.queryDepInfosFromName(env, pName, required)
|
|
125
|
+
return false if dInfos == nil
|
|
126
|
+
return _push(env, dInfos)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Return if there is a dep_into to the envType name
|
|
130
|
+
def exists?(name)
|
|
131
|
+
return @deps[name] != nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Remove (if any) the dep_into to the envType name
|
|
135
|
+
def del(name)
|
|
136
|
+
return @deps[name] = nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Get the required version string for envType name
|
|
140
|
+
def get_version(name)
|
|
141
|
+
return nil if @deps[name] == nil
|
|
142
|
+
return @deps[name][:version]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Get the required SHA1 string for envType name
|
|
146
|
+
def get_sha1(name)
|
|
147
|
+
return nil if @deps[name] == nil
|
|
148
|
+
return @deps[name][:sha1]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Iterator on dep_infos
|
|
152
|
+
#
|
|
153
|
+
# Block args are (envType, dep_info)
|
|
154
|
+
def each()
|
|
155
|
+
@deps.each(){|name, h|
|
|
156
|
+
yield name, h
|
|
157
|
+
}
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Generates a string with a human reable list of all dep_infos
|
|
161
|
+
def to_s
|
|
162
|
+
str = ""
|
|
163
|
+
@deps.each(){|name, h|
|
|
164
|
+
str+= "\t" + name.to_s.ljust(20) + "=> " + h[:version].to_s + " (" + h[:sha1].to_s + ")\n"
|
|
165
|
+
}
|
|
166
|
+
return str
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Returns true if there is no dep_info
|
|
170
|
+
def empty?
|
|
171
|
+
return @deps.empty?
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Compare two Dependencies
|
|
175
|
+
#
|
|
176
|
+
# This make sure all dep_infos are the sames in the two
|
|
177
|
+
def ==(another)
|
|
178
|
+
begin
|
|
179
|
+
@deps.each(){|name, h|
|
|
180
|
+
return false if another.deps[name] != h
|
|
181
|
+
}
|
|
182
|
+
another.each(){|name, h|
|
|
183
|
+
return false if @deps[name] != h
|
|
184
|
+
}
|
|
185
|
+
return true
|
|
186
|
+
rescue => e
|
|
187
|
+
return false
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Concat another Dependencies object into this one
|
|
192
|
+
#
|
|
193
|
+
# Throws exception if both are incompatible
|
|
194
|
+
def concat(another)
|
|
195
|
+
if another != nil then
|
|
196
|
+
another.each(){|name, h|
|
|
197
|
+
_push(name, h)
|
|
198
|
+
}
|
|
199
|
+
if another.partialEnv == true
|
|
200
|
+
@partialEnv = true
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
return self
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module WorkEnvs
|
|
4
|
+
|
|
5
|
+
# Name of the no dkms options
|
|
6
|
+
WENV_OPTS_NODKMS = "nodkms"
|
|
7
|
+
# Help string for the no dkms options
|
|
8
|
+
WENV_OPTS_NODKMS_STRING =
|
|
9
|
+
"\t#{WENV_OPTS_NODKMS}=false Build DKMS modules"
|
|
10
|
+
|
|
11
|
+
# Name of the no eclipse options
|
|
12
|
+
WENV_OPTS_NOECLIPSE = "noeclipse"
|
|
13
|
+
# Help string for the no eclipse options
|
|
14
|
+
WENV_OPTS_NOECLIPSE_STRING =
|
|
15
|
+
"\t#{WENV_OPTS_NOECLIPSE}=true Do not install eclipse plugins"
|
|
16
|
+
|
|
17
|
+
# Name of the external options
|
|
18
|
+
WENV_OPTS_EXTERNAL = "external"
|
|
19
|
+
# Help string for the external options
|
|
20
|
+
WENV_OPTS_EXTERNAL_STRING =
|
|
21
|
+
"\t#{WENV_OPTS_EXTERNAL}=true Do not install internal packages "
|
|
22
|
+
|
|
23
|
+
# Name of the partial options
|
|
24
|
+
WENV_OPTS_PARTIAL = "partial"
|
|
25
|
+
# Help string for the partial options
|
|
26
|
+
WENV_OPTS_PARTIAL_STRING =
|
|
27
|
+
"\t#{WENV_OPTS_PARTIAL}=true Support partially checked out environment "
|
|
28
|
+
|
|
29
|
+
# Name of the remote install options
|
|
30
|
+
WENV_OPTS_REMOTE_INSTALL = "remote-install"
|
|
31
|
+
# Help string for the remote install options
|
|
32
|
+
WENV_OPTS_REMOTE_INSTALL_STRING =
|
|
33
|
+
"\t#{WENV_OPTS_REMOTE_INSTALL}=false Disable install of packages on remote "
|
|
34
|
+
|
|
35
|
+
# Name of the remote host options
|
|
36
|
+
WENV_OPTS_REMOTE_HOST_INSTALL = "remote-host"
|
|
37
|
+
# Help string for the remote host options
|
|
38
|
+
WENV_OPTS_REMOTE_HOST_INSTALL_STRING =
|
|
39
|
+
"\t#{WENV_OPTS_REMOTE_HOST_INSTALL}=<host> Install of packages on the specified remote host "
|
|
40
|
+
|
|
41
|
+
# Name of the const options
|
|
42
|
+
WENV_OPTS_CONST = "const"
|
|
43
|
+
# Help string for the const options
|
|
44
|
+
WENV_OPTS_CONST_STRING =
|
|
45
|
+
"\t#{WENV_OPTS_CONST}=true Remove all write rights to environment so it cannot be modified"
|
|
46
|
+
|
|
47
|
+
# Name of the sparse options
|
|
48
|
+
WENV_OPTS_SPARSE = "sparse"
|
|
49
|
+
# Help string for the sparse options
|
|
50
|
+
WENV_OPTS_SPARSE_STRING =
|
|
51
|
+
"\t#{WENV_OPTS_SPARSE}=true Sparse update of the env (skip some unneeded packages"
|
|
52
|
+
|
|
53
|
+
# Class to store envClass options
|
|
54
|
+
class EnvOpts
|
|
55
|
+
# Default constructor
|
|
56
|
+
def initialize
|
|
57
|
+
@opts = {}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Iterates on all options set
|
|
61
|
+
#
|
|
62
|
+
# Block args are (option name, option val)
|
|
63
|
+
def each()
|
|
64
|
+
@opts.each(){|name, val|
|
|
65
|
+
yield name, val
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns true if there are no options set
|
|
70
|
+
def empty?
|
|
71
|
+
return @opts.empty?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns the value of the option "name"
|
|
75
|
+
#
|
|
76
|
+
# Returns "" if the option was not set
|
|
77
|
+
def [](name)
|
|
78
|
+
return "" if @opts[name] == nil
|
|
79
|
+
return @opts[name]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# Set the value of the option "name"
|
|
84
|
+
#
|
|
85
|
+
# Returns its value
|
|
86
|
+
def []=(name, val)
|
|
87
|
+
@opts[name] = val
|
|
88
|
+
return val
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Parse an option string and add it to self
|
|
92
|
+
#
|
|
93
|
+
# String format is name=val
|
|
94
|
+
#
|
|
95
|
+
# val cannot contain an "=" symbol
|
|
96
|
+
def <<(string)
|
|
97
|
+
args = string.split("=")
|
|
98
|
+
raise("Unsupported option #{string}") if args.length != 2
|
|
99
|
+
@opts[args[0]] = args[1];
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Compare two EnvOpts
|
|
103
|
+
def ==(another)
|
|
104
|
+
begin
|
|
105
|
+
@opts.each(){|name, val|
|
|
106
|
+
return false if another[name] != val
|
|
107
|
+
}
|
|
108
|
+
another.each(){|name, val|
|
|
109
|
+
return false if @opts[name] != val
|
|
110
|
+
}
|
|
111
|
+
return true
|
|
112
|
+
rescue
|
|
113
|
+
return false
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Concat another EnvOpts into this one
|
|
118
|
+
#
|
|
119
|
+
# Value set in this one are NOT overwritten by the other one
|
|
120
|
+
def concat(another)
|
|
121
|
+
if another != nil then
|
|
122
|
+
another.each(){|name, val|
|
|
123
|
+
@opts[name] = val if @opts[name] == nil || @opts[name] == ""
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
return self
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module WorkEnvs
|
|
4
|
+
# Class to briefly describe a MAIN_PACKAGE of an envClass
|
|
5
|
+
#
|
|
6
|
+
# This is only used to get a list of possible MAIN_PACKAGE version
|
|
7
|
+
# of a given class to provide a human readable list of accessible package
|
|
8
|
+
class EnvPackage
|
|
9
|
+
# Full name of the package
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# SHA1 that generated the package
|
|
12
|
+
attr_reader :sha1
|
|
13
|
+
# Package the branch was generated on
|
|
14
|
+
attr_reader :branch
|
|
15
|
+
# Additional info (timestamp usually) on the package
|
|
16
|
+
attr_reader :info
|
|
17
|
+
|
|
18
|
+
# Default Constructor
|
|
19
|
+
def initialize(name, sha1, branch, info)
|
|
20
|
+
@name = name
|
|
21
|
+
@sha1 = sha1
|
|
22
|
+
@branch = branch
|
|
23
|
+
@info = info
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns a human readable string of the package data
|
|
27
|
+
def to_s()
|
|
28
|
+
return "\t" + @name.to_s.ljust(65) + "\t" +
|
|
29
|
+
@sha1.to_s + "\t" +
|
|
30
|
+
@branch.to_s.ljust(40) +
|
|
31
|
+
@info.to_s
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Class to describe a package
|
|
36
|
+
class Package
|
|
37
|
+
|
|
38
|
+
# Package name (without version/release/etc)
|
|
39
|
+
#
|
|
40
|
+
# Also known as "project" in de DB
|
|
41
|
+
attr_accessor :name
|
|
42
|
+
# Package attributes (default = {}
|
|
43
|
+
#
|
|
44
|
+
# Currently supported attributes:
|
|
45
|
+
# - :install
|
|
46
|
+
# - :dkms : Packet is installed during an env update when --install-dkms is set
|
|
47
|
+
# - :install: Packet is always installed during an env update. SHOULD NOT BE SET
|
|
48
|
+
# - :keep : Package is kept after download/extraction event if keep-packages is not set
|
|
49
|
+
attr_accessor :attributes
|
|
50
|
+
# Full package name (ie name-version-release.rpm)
|
|
51
|
+
attr_accessor :pack
|
|
52
|
+
# Full path to the package
|
|
53
|
+
attr_accessor :path
|
|
54
|
+
|
|
55
|
+
# Default constructor
|
|
56
|
+
def initialize(name, attributes = {}, pack=nil)
|
|
57
|
+
@name = name
|
|
58
|
+
@attributes = attributes
|
|
59
|
+
@pack = pack
|
|
60
|
+
@path = nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Returns the package name
|
|
64
|
+
def to_s()
|
|
65
|
+
return @name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Compare two Package objects themselves (not the content)
|
|
69
|
+
#
|
|
70
|
+
# Used for sorting
|
|
71
|
+
def eql?(other)
|
|
72
|
+
return self == other
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Compare two Package objects values
|
|
76
|
+
def ==(other)
|
|
77
|
+
return false if other == nil
|
|
78
|
+
return self.hash() == other.hash()
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Spaceship operation
|
|
82
|
+
#
|
|
83
|
+
# Calls <=> on full package names
|
|
84
|
+
#
|
|
85
|
+
# Used for sorting
|
|
86
|
+
def <=>(other)
|
|
87
|
+
return @pack <=> other.pack()
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns a Package hash
|
|
91
|
+
#
|
|
92
|
+
# Used for sorting
|
|
93
|
+
def hash()
|
|
94
|
+
return { :name => @name, :attributes => @attributes, :pack => @pack, :path => @path }.hash()
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns true if the package should be installed
|
|
98
|
+
#
|
|
99
|
+
# A package should be installed if:
|
|
100
|
+
# - it has the attribute :install == true
|
|
101
|
+
# - it has the attribute :install == :dkms and :installDKMS options is set
|
|
102
|
+
def shouldInstall(opts)
|
|
103
|
+
return @attributes[:install] == true ||
|
|
104
|
+
( @attributes[:install] == :dkms && opts[:installDKMS] == true)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Returns true if the package should be kept after download/extraction
|
|
108
|
+
#
|
|
109
|
+
# A package should be kept if:
|
|
110
|
+
# - it has the attribute :keep == true
|
|
111
|
+
# - it the :keepPackages options is set
|
|
112
|
+
def shouldKeep(opts)
|
|
113
|
+
return @attributes[:keep] == true || opts[:keepPackages] == true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|