nub 0.0.75 → 0.0.76

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 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