nub 0.0.75 → 0.0.76

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5999fb1317e9737b0f1635fabedbf445f5c721fba5b3bbe3840e4877cce3014
4
- data.tar.gz: 77d77b46e2b950b39d9de2b21fee171e90a5e980080dc7d835a062657e8368c5
3
+ metadata.gz: fa43f1a038ebba265bc6b032dcb802cd5870e9b1cc703fe46fb5a96f6240d71a
4
+ data.tar.gz: 5f6201fb958875f52935cb9b0257831671d3dd3db21f2ccbcb49356fdd1cf8d8
5
5
  SHA512:
6
- metadata.gz: 2e14f4967da9531fbd776dae27ac96371941706bbdfff3f6c7705d31f5cc5a4be3515c8367678bcaf86f5372d19dd0bbf59535ee039309c35679a929c84e21ee
7
- data.tar.gz: 4277a647369fd8911c48bc22cf8b77cfdfbd496cd5d0d9e3b1e1f9d9be03e751fe9ff98d5158b19e2c0e70d294ca763299522583c7bd50709fd4d2608aeb8f58
6
+ metadata.gz: da19249c6af9fac56ac2d8c7ec4c6a525792bbca53fe1b63b8dc5e47c0439e525b5e918ddfdc82fb820579e708dc4ed12602722491638f4be3681701e9d75019
7
+ data.tar.gz: 902fbbaae0773ca9cd7a36b6d3575d9fba4b602ea85e3ae6789c9a599d4fc30cc5fb273bd18d7f7f71b9503027315a037199be38f0b60fc4700dd749f019c64f
data/lib/nub/core.rb CHANGED
@@ -20,6 +20,7 @@
20
20
  #SOFTWARE.
21
21
 
22
22
  require 'erb'
23
+ require 'ostruct'
23
24
 
24
25
  ColorPair = Struct.new(:str, :color_code, :color_name)
25
26
  ColorMap = {
@@ -77,6 +78,27 @@ class ERBResolve
77
78
 
78
79
  return data
79
80
  end
81
+
82
+ # Resolve variables for the given data type, changes are done inplace
83
+ # @data [string/array/hash] data to replace vars
84
+ def resolve!(data)
85
+
86
+ # Recurse
87
+ if data.is_a?(Array)
88
+ for i in 0...data.size
89
+ resolve!(data[i])
90
+ end
91
+ elsif data.is_a?(Hash)
92
+ data.each{|k,v| data[k] = resolve!(v)}
93
+ end
94
+
95
+ # Base case
96
+ if data.is_a?(String)
97
+ data.gsub!(data, ERB.new(data).result(@context))
98
+ end
99
+
100
+ return data
101
+ end
80
102
  end
81
103
 
82
104
  # Hash extensions
@@ -94,6 +116,12 @@ class Hash
94
116
  def erb(vars = {})
95
117
  ERBResolve.new(vars).resolve(self)
96
118
  end
119
+
120
+ # Easily inject ERB variables into hash values
121
+ # +vars+:: hash of variables to inject into the string
122
+ def erb!(vars = {})
123
+ ERBResolve.new(vars).resolve!(self)
124
+ end
97
125
  end
98
126
 
99
127
  # Array extensions
@@ -109,6 +137,12 @@ class Array
109
137
  def erb(vars = {})
110
138
  ERBResolve.new(vars).resolve(self)
111
139
  end
140
+
141
+ # Easily inject ERB variables into Array values
142
+ # +vars+:: hash of variables to inject into the string
143
+ def erb!(vars = {})
144
+ ERBResolve.new(vars).resolve!(self)
145
+ end
112
146
  end
113
147
 
114
148
  # Monkey patch string with some useful methods
@@ -120,6 +154,12 @@ class String
120
154
  ERBResolve.new(vars).resolve(self)
121
155
  end
122
156
 
157
+ # Easily inject ERB variables into a string
158
+ # @param vars [Hash] of variables to inject into the string
159
+ def erb!(vars = {})
160
+ ERBResolve.new(vars).resolve!(self)
161
+ end
162
+
123
163
  # Convert the string to ascii, stripping out or converting all non-ascii characters
124
164
  def to_ascii
125
165
  options = {
@@ -175,8 +215,6 @@ class String
175
215
 
176
216
  return tokens
177
217
  end
178
-
179
-
180
218
  end
181
219
 
182
220
  # vim: ft=ruby:ts=2:sw=2:sts=2
data/lib/nub/fileutils.rb CHANGED
@@ -19,11 +19,45 @@
19
19
  #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
20
  #SOFTWARE.
21
21
 
22
+ require 'digest'
22
23
  require 'fileutils'
24
+ require 'yaml'
25
+
26
+ require_relative 'core'
23
27
 
24
28
  # Monkey patch FileUtils with some useful methods
25
29
  module FileUtils
26
30
 
31
+ # Check if any digests have changed based on the given files
32
+ # @param key [yaml] yalm section heading to give digests
33
+ # @param digestfile [string] digest file to check against
34
+ # @param files [array] files to get digests for
35
+ # @returns (newfiles, modifiedfiles, deletedfiles)
36
+ def self.digests_changed?(key, digestfile, files)
37
+ files = [files] if files.is_a?(String)
38
+ newfiles, modifiedfiles, deletedfiles = [], [], []
39
+
40
+ # Since layers are stacked and the digest file may be from a lower
41
+ # layer this should be ignored unless the layer matches
42
+ if (digests = File.exist?(digestfile) ? YAML.load_file(digestfile)[key] : nil)
43
+
44
+ # New files: in files but not yaml
45
+ newfiles = files.select{|x| not digests[x]}
46
+
47
+ # Delete files: in yaml but not files
48
+ deletedfiles = digests.map{|k,v| k}.select{|x| not files.include?(x)}
49
+
50
+ # Modified files: in both but digest is different
51
+ modifiedfiles = files.select{|x| digests[x] and
52
+ Digest::MD5.hexdigest(File.binread(x)) != digests[x]}
53
+ else
54
+ newfiles = files
55
+ end
56
+
57
+ return newfiles, modifiedfiles, deletedfiles
58
+ end
59
+
60
+
27
61
  # Check PATH for executable
28
62
  # @param name [String] name of executable to find
29
63
  # @param path [Array] path to search
@@ -48,9 +82,10 @@ module FileUtils
48
82
  # @return new version
49
83
  def self.inc_version(path, regex, major:false, minor:false, rev:true, override:nil)
50
84
  version = nil
51
- self.update(path){|line|
85
+ self.update(path){|data|
52
86
 
53
87
  # Increment version
88
+ line = data.split("\n").find{|x| x[regex, 1]}
54
89
  if ver = line[regex, 1]
55
90
  new_ver = nil
56
91
  if not override
@@ -65,15 +100,92 @@ module FileUtils
65
100
 
66
101
  # Modify the original line
67
102
  version = new_ver
68
- line.gsub!(ver, new_ver)
103
+ newline = line.gsub(ver, new_ver)
104
+ data.gsub!(line, newline)
69
105
  end
70
106
  }
71
107
 
72
108
  return version
73
109
  end
74
110
 
111
+ # Insert into a file
112
+ # Location of insert is determined by the given regex and offset.
113
+ # Append is used if no regex is given.
114
+ # @param file [string] path of file to modify
115
+ # @param values [array] string or list of string values to insert
116
+ # @param regex [string] regular expression for location, not used if offset is nil
117
+ # @param offset [int] offset insert location by this amount for regexs
118
+ # @returns true if a change was made to the file
119
+ def self.insert(file, values, regex:nil, offset:1)
120
+ return false if not values or values.empty?
121
+
122
+ changed = false
123
+ values = [values] if values.is_a?(String)
124
+ FileUtils.touch(file) if not File.exist?(file)
125
+
126
+ begin
127
+ data = nil
128
+ File.open(file, 'r+') do |f|
129
+ data = f.read
130
+ lines = data.split("\n")
131
+
132
+ # Match regex for insert location
133
+ regex = Regexp.new(regex) if regex.is_a?(String)
134
+ i = regex ? lines.index{|x| x =~ regex} : lines.size
135
+ return false if not i
136
+ i += offset if regex and offset
137
+
138
+ # Insert at offset
139
+ values.each{|x|
140
+ lines.insert(i, x) and i += 1
141
+ changed = true
142
+ }
143
+
144
+ # Truncate then write out new content
145
+ f.seek(0)
146
+ f.truncate(0)
147
+ f.puts(lines)
148
+ end
149
+ rescue
150
+ # Revert back to the original incase of failure
151
+ File.open(file, 'w'){|f| f << data} if data
152
+ raise
153
+ end
154
+
155
+ return changed
156
+ end
157
+
158
+
159
+ # Replace in file
160
+ # @param file [string] file to modify
161
+ # @param regex [string] regular expression match on
162
+ # @param value [string] regular expression string replacement
163
+ # @returns true on change
164
+ def self.replace(file, regex, value)
165
+ changed = self.update(file){|data|
166
+ lines = data.split("\n")
167
+
168
+ # Search replace
169
+ regex = Regexp.new(regex) if regex.is_a?(String)
170
+ lines.each{|x| x.gsub!(regex, value)}
171
+
172
+ # Change data inline
173
+ data.gsub!(data, lines * "\n")
174
+ }
175
+
176
+ return changed
177
+ end
178
+
179
+ # Resolve template
180
+ # @param file [string] file to resolve templates for
181
+ # @param vars [hash/ostruct] templating variables to use while resolving
182
+ # @returns true on change
183
+ def self.resolve(file, vars)
184
+ return self.update(file){|data| data.erb!(vars)}
185
+ end
186
+
75
187
  # Update the file using a block, revert on failure.
76
- # Use this for simple line edits. Block is passed in each line of the file
188
+ # Use this for file edits. Block is passed in the file data
77
189
  # @param filename [String] name of the file to change
78
190
  # @return true on change
79
191
  def self.update(filename)
@@ -81,23 +193,25 @@ module FileUtils
81
193
  block = Proc.new # Most efficient way to get block
82
194
 
83
195
  begin
84
- lines = nil
196
+ data = nil
85
197
  File.open(filename, 'r+'){|f|
86
- lines = f.readlines
87
- lines.each{|line|
88
- line_copy = line.dup
89
- block.call(line)
90
- changed |= line_copy != line
91
- }
198
+ data = f.read
199
+ data_orig = data.dup
200
+
201
+ # Call block
202
+ block.call(data)
203
+ changed |= data_orig != data
92
204
 
93
205
  # Save the changes back to the file
94
- f.seek(0)
95
- f.truncate(0)
96
- f.puts(lines)
206
+ if changed
207
+ f.seek(0)
208
+ f.truncate(0)
209
+ f << data
210
+ end
97
211
  }
98
- rescue
212
+ rescue Exception => e
99
213
  # Revert back to the original incase of failure
100
- File.open(filename, 'w'){|f| f.puts(lines)} if lines
214
+ File.open(filename, 'w'){|f| f << data} if data
101
215
  raise
102
216
  end
103
217
 
@@ -112,21 +226,41 @@ module FileUtils
112
226
  def self.update_copyright(path, copyright, year:Time.now.year)
113
227
  set_copyright = false
114
228
 
115
- changed = self.update(path){|line|
229
+ changed = self.update(path){|data|
230
+ line = data.split("\n").find{|x| x[/#{Regexp.quote(copyright)}/]}
116
231
  if !set_copyright && line =~ /#{Regexp.quote(copyright)}/
117
232
  set_copyright = true
118
233
  _year = line[/#{Regexp.quote(copyright)}\s+((\d{4}\s)|(\d{4}-\d{4})).*/, 1].strip
119
234
  if _year.include?("-")
120
235
  years = _year.split("-")
121
- line.gsub!(_year, "#{years.first}-#{year}") if years.last != year
236
+ if years.last != year
237
+ newline = line.gsub(_year, "#{years.first}-#{year}")
238
+ data.gsub!(line, newline)
239
+ end
122
240
  elsif prev_year = _year != year.to_s ? year.to_i - 1 : nil
123
- line.gsub!(_year.to_s, "#{prev_year}-#{year}")
241
+ newline = line.gsub(_year.to_s, "#{prev_year}-#{year}")
242
+ data.gsub!(line, newline)
124
243
  end
125
244
  end
126
245
  }
127
246
  return changed
128
247
  end
129
248
 
249
+ # Generate digests for array of files given and save them
250
+ # @param key [yaml] yalm section heading to give digests
251
+ # @param digestfile [string] digest file to update
252
+ # @param files [array] files to get digests for
253
+ def self.update_digests(key, digestfile, files)
254
+ files = [files] if files.is_a?(String)
255
+
256
+ # Build up digests structure
257
+ digests = {}
258
+ files.each{|x| digests[x] = Digest::MD5.hexdigest(File.binread(x)) if File.exist?(x)}
259
+
260
+ # Write out digests structure as yaml with named header
261
+ File.open(digestfile, 'w'){|f| f.puts({key => digests}.to_yaml)}
262
+ end
263
+
130
264
  # Get SemVer formatted versions
131
265
  # @param path [String] file to increment version for
132
266
  # @param regex [Regex] capture pattern for version match
data/lib/nub/pacman.rb ADDED
@@ -0,0 +1,94 @@
1
+ #MIT License
2
+ #Copyright (c) 2018 phR0ze
3
+ #
4
+ #Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ #of this software and associated documentation files (the "Software"), to deal
6
+ #in the Software without restriction, including without limitation the rights
7
+ #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ #copies of the Software, and to permit persons to whom the Software is
9
+ #furnished to do so, subject to the following conditions:
10
+ #
11
+ #The above copyright notice and this permission notice shall be included in all
12
+ #copies or substantial portions of the Software.
13
+ #
14
+ #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ #SOFTWARE.
21
+
22
+ require 'fileutils'
23
+ require_relative 'log'
24
+ require_relative 'sys'
25
+ require_relative 'module'
26
+
27
+ # Wrapper around system Arch Linux pacman
28
+ module Pacman
29
+ extend self
30
+ mattr_accessor(:path, :config, :sysroot)
31
+
32
+ # Configure pacman for the given root
33
+ # @param path [String] path where all pacman artifacts will be (i.e. logs, cache etc...)
34
+ # @param config [String] config file path to use, note gets copied in
35
+ # @param sysroot [String] path to the system root to use
36
+ def init(path, config, sysroot)
37
+ self.path = path
38
+ self.sysroot = sysroot
39
+ self.config = File.join(path, File.basename(config))
40
+
41
+ # Validate incoming params
42
+ Log.die("pacman path '#{path}' doesn't exist") unless Dir.exist?(path)
43
+ Log.die("pacman sysroot '#{sysroot}' doesn't exist") unless Dir.exist?(sysroot)
44
+ Log.die("pacman config file '#{config}' doesn't exist") unless File.exist?(config)
45
+
46
+ # Update the given pacman config file to use the given path
47
+ FileUtils.rm_rf(File.join(path, '.'))
48
+ FileUtils.cp(config, path, preserve: true)
49
+
50
+ Sys.exec("cp -a #{@pacman_src_mirrors} #{@pacman_path}")
51
+ Fedit.replace(@pacman_conf, /(Architecture = ).*/, "\\1#{@vars.arch}")
52
+ # Leave DBPath set as /var/lib/pacman and copy out sync
53
+ Fedit.replace(@pacman_conf, /#(CacheDir\s+= ).*/, "\\1#{File.join(@pacman_path, 'cache')}")
54
+ Fedit.replace(@pacman_conf, /#(LogFile\s+= ).*/, "\\1#{File.join(@pacman_path, 'pacman.log')}")
55
+ Fedit.replace(@pacman_conf, /#(GPGDir\s+= ).*/, "\\1#{File.join(@pacman_path, 'gnupg')}")
56
+ Fedit.replace(@pacman_conf, /#(HookDir\s+= ).*/, "\\1#{File.join(@pacman_path, 'hooks')}")
57
+ Fedit.replace(@pacman_conf, /.*(\/.*mirrorlist).*/, "Include = #{@pacman_path}\\1")
58
+
59
+ repos = Dir[File.join(@pacman_path, "*.mirrorlist")].map{|x| File.basename(x, '.mirrorlist')}
60
+ Sys.exec("pacman-key --config #{@pacman_conf} --init")
61
+ Sys.exec("pacman-key --config #{@pacman_conf} --populate #{repos * ' '}")
62
+
63
+ # Initialize pacman keyring
64
+ #Sys.exec("pacman-key --config #{self.config} --init")
65
+ #Sys.exec("pacman-key --config #{self.config} --populate #{repos * ' '}")
66
+ end
67
+
68
+ # Update the pacman database
69
+ def update
70
+ success = false
71
+ while not success
72
+ begin
73
+ cmd = "pacman -Sy"
74
+ cmd += " --sysroot #{self.sysroot}" if self.sysroot
75
+ Sys.exec(cmd)
76
+ success = true
77
+ rescue Exception => e
78
+ puts(e.message)
79
+ end
80
+ end
81
+ end
82
+
83
+ # Install the given packages
84
+ # @param pkgs [Array] List of packages to install
85
+ def install()
86
+ puts("Pacstrap package installs for '#{deployment}'...".colorize(:cyan))
87
+ cmd = ['pacstrap', '-GMc', deployment_work, '--config', @pacman_conf, '--needed', *apps[:reg]]
88
+ cmd += ['--ignore', apps[:ignore] * ','] if apps[:ignore].any?
89
+ !puts("Error: Failed to install packages correctly".colorize(:red)) and
90
+ exit unless Sys.exec(cmd, env:@proxyenv)
91
+ end
92
+ end
93
+
94
+ # vim: ft=ruby:ts=2:sw=2:sts=2
data/lib/nub/sys.rb CHANGED
@@ -107,19 +107,6 @@ module Sys
107
107
  return pass
108
108
  end
109
109
 
110
- # Update pacman database
111
- def pacman_update
112
- success = false
113
- while not success
114
- begin
115
- Sys.exec("pacman -Sy")
116
- success = true
117
- rescue Exception => e
118
- puts(e.message)
119
- end
120
- end
121
- end
122
-
123
110
  # Remove given dir or file
124
111
  # Params:
125
112
  # +path+:: path to delete
data/lib/nub.rb CHANGED
@@ -30,6 +30,7 @@ module Nub
30
30
  require 'nub/log'
31
31
  require 'nub/module'
32
32
  require 'nub/net'
33
+ require 'nub/pacman'
33
34
  require 'nub/thread_comm'
34
35
  require 'nub/user'
35
36
  require 'nub/sys'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.75
4
+ version: 0.0.76
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Crummett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-11 00:00:00.000000000 Z
11
+ date: 2018-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -97,6 +97,7 @@ files:
97
97
  - lib/nub/log.rb
98
98
  - lib/nub/module.rb
99
99
  - lib/nub/net.rb
100
+ - lib/nub/pacman.rb
100
101
  - lib/nub/sys.rb
101
102
  - lib/nub/thread_comm.rb
102
103
  - lib/nub/user.rb