slack-utils 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -38,7 +38,7 @@ TODO:
38
38
  == Installation
39
39
 
40
40
  To install the gem
41
- sudo gem install pkg/slack-utils-0.5.3.gem
41
+ sudo gem install pkg/slack-utils-0.6.0.gem
42
42
 
43
43
  == Quick Start
44
44
 
File without changes
data/examples/repo.rb CHANGED
File without changes
File without changes
data/lib/slackware.rb CHANGED
@@ -2,4 +2,5 @@
2
2
  require 'slackware/version'
3
3
  require 'slackware/package'
4
4
  require 'slackware/system'
5
+ require 'slackware/changelog'
5
6
  require 'slackware/repo'
@@ -0,0 +1,238 @@
1
+
2
+ require 'slackware/package'
3
+ require 'date'
4
+ require 'time'
5
+
6
+ module Slackware
7
+ # The class for parsing a Slackware standard ChangeLog.txt
8
+ class ChangeLog
9
+
10
+ # yanked from +Date+
11
+ ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
12
+ ABBR_MONTHNAMES = %w(Jan Feb Mar Apr May Jun
13
+ Jul Aug Sep Oct Nov Dec)
14
+
15
+ # Compiling a fat regex to find the date entries
16
+ re_daynames = Regexp.new(ABBR_DAYNAMES.join('|'))
17
+ re_monthnames = Regexp.new(ABBR_MONTHNAMES.join('|'))
18
+ RE_DATE = Regexp.new(/^(#{re_daynames}\s+#{re_monthnames}\s+\d+\s+\d{2}:\d{2}:\d{2}\s\w+\s+\d+)$/)
19
+
20
+ # This break has been the same as long as I can find
21
+ RE_CHANGELOG_BREAK = Regexp.new(/^\+--------------------------\+$/)
22
+
23
+ # The regular entry, accounting for usb-and-pxe-installers directory,
24
+ # and notes after the action
25
+ re_package_entry0 = Regexp.new(/^(([\w+-]+).*\/.*):\s+(\w+).*\.?$/)
26
+ # Some didn't have an action after the name
27
+ re_package_entry1 = Regexp.new(/^(([\w+-]+).*\/.*):/)
28
+ # and some didn't have the ':' or an action
29
+ re_package_entry2 = Regexp.new(/^(([\w+-]+).*\/.*\.t[gbx]z)/)
30
+ # combine them
31
+ RE_PACKAGE_ENTRY = Regexp.union(re_package_entry0, re_package_entry1, re_package_entry2)
32
+
33
+ # (* Security fix *)
34
+ RE_SECURITY_FIX = Regexp.new(/\(\*\s+security\s+fix\s+\*\)/i)
35
+
36
+ # for hacks sake, make these usbable elsewhere
37
+ def self::re_date ; RE_DATE ; end
38
+ def self::re_changelog_break ; RE_CHANGELOG_BREAK ; end
39
+ def self::re_package_entry ; RE_PACKAGE_ENTRY ; end
40
+ def self::re_security_fix ; RE_SECURITY_FIX ; end
41
+
42
+ # A changeset, which should consist of entries of changes and/or notes
43
+ # regarding the updates
44
+ class Update
45
+ # FIXME this class needs more proper value setting
46
+ def initialize(date = nil, notes = "", entries = Array.new)
47
+ @date = date
48
+ @notes = notes
49
+ @entries = entries
50
+ end
51
+ def date; @date; end
52
+ def notes; @notes; end
53
+ def entries; @entries; end
54
+
55
+ def date=(timestamp)
56
+ if (timestamp.is_a?(Time))
57
+ @date = timestamp
58
+ elsif (timestamp.is_a?(Date))
59
+ @date = timestamp.to_time
60
+ else
61
+ @date = Time.parse(timestamp)
62
+ end
63
+ end
64
+ def notes=(text); @notes = text; end
65
+ end
66
+
67
+ # The class for each item in a change set
68
+ class Entry
69
+ def initialize(package = nil, section = nil, action = nil, notes = "", security = false)
70
+ @package = package
71
+ @section = section
72
+ @action = action
73
+ notes.is_a?(String) ? @notes = notes : @notes = ""
74
+ security == true ? @security = security : @security = false
75
+ end
76
+
77
+ def package; @package; end
78
+ def section; @section; end
79
+ def action; @action; end
80
+ def notes; @notes; end
81
+ def security; @security; end
82
+
83
+ def package=(package_name); @package = package_name ; end
84
+ def section=(section_name); @section = section_name ; end
85
+ def action=(action_name); @action = action_name ; end
86
+ def notes=(notes_txt)
87
+ notes_txt.is_a?(String) ? @notes = notes_txt : @notes = ""
88
+ end
89
+ def security=(bool)
90
+ bool == true ? @security = bool : @security = false
91
+ end
92
+ end
93
+
94
+ # +file+ can be a path to a file, or a +File+ object
95
+ # +opts+ can include
96
+ # * :arch - basically '64' or '32'
97
+ # * :version - 13.1, 13.2, current, etc.
98
+ # * :url - the URL web link to the ChangeLog.txt
99
+ def initialize(file = nil, opts = {})
100
+ @file = file
101
+ @opts = opts
102
+ @updates = Array.new
103
+ end
104
+
105
+ def file; @file; end
106
+ def opts; @opts; end
107
+ def updates; @updates; end
108
+ def entries
109
+ @updates.map {|update| update.entries.map {|entry| {:date => update.date, :entry => entry } } }.flatten
110
+ end
111
+ def security
112
+ @updates.map {|u| u.entries.map {|e| {:date => u.date, :entry => e } if e.security } }.flatten.compact
113
+ end
114
+ def opts=(hash)
115
+ if hash.is_a?(Hash)
116
+ @opts = hash
117
+ end
118
+ end
119
+
120
+ def parse
121
+ unless @file.nil?
122
+ @updates = parse_this_file(@file).updates
123
+ end
124
+ return self
125
+ end
126
+
127
+ # Class method
128
+ def self::parse(file)
129
+ return parse_this_file(file)
130
+ end
131
+
132
+ def self::open(file)
133
+ return parse_this_file(file)
134
+ end
135
+
136
+ def inspect
137
+ "#<%s:0x%x @file=%s, %d @updates, %d @entries>" % [self.class.name, self.object_id.abs, self.file || '""', self.updates.count || 0, self.entries.count || 0]
138
+ end
139
+
140
+ private
141
+ # Parse order is something like:
142
+ # * if its' a date match, store the date
143
+ # * take change notes until
144
+ # * package match on name and action
145
+ # * set @security if present
146
+ # * take packge notes until
147
+ # * next package or entry separator
148
+ # * separator creates next change entry
149
+ def parse_this_file(file)
150
+ f_handle = ""
151
+ if file.is_a?(File)
152
+ f_handle = file
153
+ elsif file.is_a?(String)
154
+ if File.exist?(File.expand_path(file))
155
+ f_handle = File.open(File.expand_path(file))
156
+ else
157
+ raise StandardError.new("file not found\n")
158
+ end
159
+ else
160
+ raise StandardError.new("file not found\n")
161
+ end
162
+
163
+ # Start our changelog
164
+ changelog = ChangeLog.new(f_handle)
165
+ f_handle.each do |line|
166
+ if (line =~ RE_DATE)
167
+ u = Update.new(Time.parse($1))
168
+ while true
169
+ if (f_handle.eof?)
170
+ break
171
+ end
172
+
173
+ # take the next line
174
+ u_line = f_handle.readline
175
+ if (u_line =~ RE_CHANGELOG_BREAK)
176
+ break
177
+ end
178
+
179
+ # the intimate iteration
180
+ # +Match+ is more expensive than =~,
181
+ # but ruby-1.8.x is lossing the matched values down below
182
+ # so this works on both ...
183
+ if (match = RE_PACKAGE_ENTRY.match(u_line))
184
+ u_entry = Entry.new()
185
+ # This silly iteration catches the different cases of
186
+ # which package line, matches which Regexp. WIN
187
+ if match[1].nil?
188
+ if match[4].nil?
189
+ u_entry.package = match[6] unless match[6].nil?
190
+ else
191
+ u_entry.package = match[4]
192
+ end
193
+ else
194
+ u_entry.package = match[1]
195
+ end
196
+ if u_entry.package.include?("/")
197
+ u_entry.package = u_entry.package.split("/")[-1]
198
+ end
199
+ if match[2].nil?
200
+ if match[5].nil?
201
+ u_entry.section = match[7] unless match[7].nil?
202
+ else
203
+ u_entry.section = match[5]
204
+ end
205
+ else
206
+ u_entry.section = match[2]
207
+ end
208
+ # set the action for the item, if it's present
209
+ u_entry.action = match[3] unless match[3].nil?
210
+
211
+ # Add this entry to the stack
212
+ u.entries << u_entry
213
+ else
214
+ # if u.entries is empty, then this text is notes
215
+ # for the upate, else it is notes, for the entry
216
+ if (u.entries.empty?)
217
+ u.notes = u.notes + u_line
218
+ else
219
+ # if this line of the entry security fix, toggle the bool
220
+ if (u_line =~ RE_SECURITY_FIX)
221
+ u.entries[-1].security = true
222
+ end
223
+ u.entries[-1].notes = u.entries[-1].notes + u_line
224
+ end
225
+ end
226
+ end
227
+
228
+ # Add this update to the stack
229
+ changelog.updates << u
230
+ end
231
+ end
232
+
233
+ # Give them their change set
234
+ return changelog
235
+ end
236
+
237
+ end
238
+ end
@@ -0,0 +1,87 @@
1
+ require 'rss/maker'
2
+ require 'slackware/changelog'
3
+
4
+ module Slackware
5
+ class ChangeLog
6
+ def to_rss
7
+ version = "2.0" # ["0.9", "1.0", "2.0"]
8
+ content = RSS::Maker.make(version) do |m|
9
+ added_title = ""
10
+ if @opts[:arch]
11
+ added_title = added_title + "slackware#{@opts[:arch]}"
12
+ end
13
+ if @opts[:version]
14
+ added_title = added_title + "-#{@opts[:version]}"
15
+ end
16
+
17
+ if added_title.empty?
18
+ m.channel.title = "Slackware ChangeLog.txt feed"
19
+ else
20
+ m.channel.title = "Slackware ChangeLog.txt feed for #{added_title}"
21
+ end
22
+ if @opts[:url]
23
+ m.channel.link = "%s#slackagg" % [@opts[:url]]
24
+ else
25
+ m.channel.link = "http://www.slackware.com/#slackagg"
26
+ end
27
+ #m.channel.logo = "http://connie.slackware.com/~msimons/slackware/grfx/shared/bluepiSW.jpg"
28
+ m.channel.logo = "http://connie.slackware.com/~msimons/slackware/grfx/shared/dobbslack1.jpg"
29
+ m.channel.description = "a parsed ChangeLog.txt, is an extendable ChangeLog.txt"
30
+ m.items.do_sort = true # sort items by date
31
+
32
+ @updates.each {|update|
33
+ i = m.items.new_item
34
+ # Add a plug to the title of the update, if it includes a security fix
35
+ # set this here, so we don't have to .map again down below
36
+ security = update.entries.map {|e| 1 if e.security }.compact.count
37
+ if (security > 0)
38
+ i.title = "%s (* Security fix *)" % [update.date.utc.to_s]
39
+ else
40
+ i.title = update.date.utc.to_s
41
+ end
42
+ if @opts[:url]
43
+ i.link = "%s#%s" % [@opts[:url], update.date.to_i]
44
+ else
45
+ i.link = "http://slackware.com/#slackagg#%s" % [update.date.to_i]
46
+ end
47
+ i.date = update.date
48
+
49
+ i.description = ""
50
+ if (update.entries.count > 0)
51
+ if (security > 0)
52
+ i.description = "%d new update(s), %d security update(s)\n\n" % [update.entries.count, security]
53
+ else
54
+ i.description = "%d new update(s)\n\n" % [update.entries.count]
55
+ end
56
+ end
57
+ i.description = i.description + "<pre><blockquote>\n"
58
+ unless (update.notes.empty?)
59
+ i.description = i.description + update.notes + "\n\n"
60
+ end
61
+ if (update.entries.count > 0)
62
+ update.entries.each {|entry|
63
+ if (entry.notes.empty?)
64
+ i.description = i.description + sprintf("%s/%s:\s%s\n",
65
+ entry.section,
66
+ entry.package,
67
+ entry.action)
68
+ else
69
+ i.description = i.description + sprintf("%s/%s:\s%s\n\s\s%s\n",
70
+ entry.section,
71
+ entry.package,
72
+ entry.action,
73
+ entry.notes)
74
+ end
75
+ }
76
+ end
77
+ i.description = i.description + "</blockquote></pre>\n"
78
+ i.description.gsub!(/\n/, "<br/>\n")
79
+ }
80
+ end
81
+ return content
82
+ end
83
+ end
84
+ end
85
+
86
+
87
+
@@ -18,8 +18,8 @@ module Slackware
18
18
  name = $1
19
19
  self.upgrade_time = Time.strptime($2 + ' ' + $3, fmt='%F %H:%M:%S')
20
20
  end
21
- arr = name.split('-').reverse
22
- build = arr.shift
21
+ arr = name.split('-')
22
+ build = arr.pop
23
23
  if (build.include?("_"))
24
24
  self.tag_sep = "_"
25
25
  self.build = build.split(self.tag_sep)[0]
@@ -29,10 +29,11 @@ module Slackware
29
29
  self.tag = $2
30
30
  else
31
31
  self.build = build
32
+ self.tag = ""
32
33
  end
33
- self.arch = arr.shift
34
- self.version = arr.shift
35
- self.name = arr.reverse.join('-')
34
+ self.arch = arr.pop
35
+ self.version = arr.pop
36
+ self.name = arr.join('-')
36
37
  end
37
38
 
38
39
  # Package.parse class method
@@ -54,8 +55,8 @@ module Slackware
54
55
 
55
56
  # Accessor for the PACKAGE DESCRIPTION from the package file
56
57
  def package_description
57
- if not(self.package_description.nil?)
58
- return self.package_description
58
+ if not(@package_description.nil?)
59
+ return @package_description
59
60
  end
60
61
 
61
62
  f = File.open(self.path + '/' + self.fullname)
@@ -69,13 +70,13 @@ module Slackware
69
70
 
70
71
  # Setter for the PACKAGE DESCRIPTION, in the event you are parsing a repo file
71
72
  def package_description=(desc)
72
- self.package_description = desc
73
+ @package_description = desc
73
74
  end
74
75
 
75
76
  # Accessor for the PACKAGE LOCATION from the package file
76
77
  def package_location
77
- if not(self.package_location.nil?)
78
- return self.package_location
78
+ if not(@package_location.nil?)
79
+ return @package_location
79
80
  end
80
81
 
81
82
  f = File.open(self.path + '/' + self.fullname)
@@ -88,13 +89,13 @@ module Slackware
88
89
 
89
90
  # Setter for the PACKAGE LOCATION, in the event you are parsing a repo file
90
91
  def package_location=(path)
91
- self.package_location = path
92
+ @package_location = path
92
93
  end
93
94
 
94
95
  # Accessor for the UNCOMPRESSED PACKAGE SIZE from the package file
95
96
  def uncompressed_size
96
- if not(self.uncompressed_size.nil?)
97
- return self.uncompressed_size
97
+ if not(@uncompressed_size.nil?)
98
+ return @uncompressed_size
98
99
  end
99
100
 
100
101
  f = File.open(self.path + '/' + self.fullname)
@@ -107,13 +108,13 @@ module Slackware
107
108
 
108
109
  # Setter for the UNCOMPRESSED PACKAGE SIZE, in the event you are parsing a repo file
109
110
  def uncompressed_size=(size)
110
- self.uncompressed_size = size
111
+ @uncompressed_size = size
111
112
  end
112
113
 
113
114
  # Accessor for the COMPRESSED PACKAGE SIZE from the package file
114
115
  def compressed_size
115
- if not(self.compressed_size.nil?)
116
- return self.compressed_size
116
+ if not(@compressed_size.nil?)
117
+ return @compressed_size
117
118
  end
118
119
 
119
120
  f = File.open(self.path + '/' + self.fullname)
@@ -126,14 +127,14 @@ module Slackware
126
127
 
127
128
  # Setter for the COMPRESSED PACKAGE SIZE, in the event you are parsing a repo file
128
129
  def compressed_size=(size)
129
- self.compressed_size = size
130
+ @compressed_size = size
130
131
  end
131
132
 
132
133
  # Accessor for the FILE LIST from the package file
133
134
  # unless the :owned_files symbol is populated
134
135
  def get_owned_files
135
- if not(self.owned_files.nil?)
136
- return self.owned_files
136
+ if not(@owned_files.nil?)
137
+ return @owned_files
137
138
  else
138
139
  f = File.open(self.path + '/' + self.fullname)
139
140
  files = f.drop_while {|l| not( l =~ /^FILE LIST:/) }[2..-1].map {|l| l.chomp }
@@ -144,8 +145,8 @@ module Slackware
144
145
 
145
146
  # Set the file list in the package object in memory
146
147
  def set_owned_files
147
- if self.owned_files.nil?
148
- self.owned_files = self.get_owned_files
148
+ if @owned_files.nil?
149
+ @owned_files = @get_owned_files
149
150
  return true
150
151
  else
151
152
  return false
@@ -158,7 +159,7 @@ module Slackware
158
159
  if (File.exist?(self.path + "/" + self.fullname))
159
160
  self.time = File.mtime(self.path + "/" + self.fullname)
160
161
  end
161
- elsif (self.time.nil? && not(self.path))
162
+ elsif (not(self.path) && (self.time.nil?))
162
163
  if (File.exist?(DIR_INSTALLED_PACKAGES + "/" + self.fullname))
163
164
  self.time = File.mtime(DIR_INSTALLED_PACKAGES + "/" + self.fullname)
164
165
  end
@@ -174,6 +175,18 @@ module Slackware
174
175
  end
175
176
  end
176
177
 
178
+ def inspect
179
+ "#<%s:0x%x name=%s version=%s arch=%s build=%s tag=%s>" % [
180
+ self.class.name,
181
+ self.object_id,
182
+ self.name,
183
+ self.version,
184
+ self.arch,
185
+ self.build,
186
+ self.tag
187
+ ]
188
+ end
189
+
177
190
  end
178
191
 
179
192
  class Script < Package
@@ -1,5 +1,6 @@
1
1
 
2
2
  require 'slackware/package'
3
+ require 'slackware/changelog'
3
4
  require 'slackware/system'
4
5
  require 'net/http'
5
6
  require 'net/ftp'
@@ -38,15 +39,17 @@ module Slackware
38
39
  end
39
40
  a
40
41
  end
42
+ else
43
+ ## do some hot parsing of repo
41
44
  end
42
45
  end
43
46
 
44
47
  def fetch(file = nil)
45
- if file.nil?
46
- url = URI.parse(self.proto + self.mirror + self.path)
47
- else
48
- url = URI.parse(self.proto + self.mirror + self.path + file)
49
- end
48
+ #if file.nil?
49
+ #url = URI.parse(self.proto + self.mirror + self.path)
50
+ #else
51
+ #url = URI.parse(self.proto + self.mirror + self.path + file)
52
+ #end
50
53
  if self.proto =~ /ftp/
51
54
  ftp = Net::FTP.open(self.mirror)
52
55
  ftp.login
@@ -63,6 +66,12 @@ module Slackware
63
66
  req = Net::HTTP::Get.new(url.path)
64
67
  res = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }
65
68
  return res
69
+ elsif self.proto =~ /file/
70
+ if (file.nil?)
71
+ return Dir.glob(self.path + "slackware" + self.arch + "-" + self.version + "/*")
72
+ else
73
+ return File.read(self.path + "slackware" + self.arch + "-" + self.version + "/" + file)
74
+ end
66
75
  else
67
76
  return nil
68
77
  end
@@ -81,8 +90,22 @@ module Slackware
81
90
  actions = %w{removed added upgraded rebuilt}
82
91
  actions.each {|action|
83
92
  changelog[:"#{action}"] = changelog_date.map {|line|
84
- if line =~ /^\w+\/(.*)\.t[gx]z:\s+#{action}\.?$/i
85
- Slackware::Package.parse($1)
93
+ if line =~ /^(\w+)\/(.*)\.t[gx]z:\s+#{action}\.?$/i
94
+ s = Slackware::Package.parse($2)
95
+ s.path = $1
96
+ if (self.mirror.nil?)
97
+ base_path= self.path
98
+ else
99
+ base_path= self.mirror + self.path
100
+ end
101
+ s.package_location = self.proto +
102
+ base_path +
103
+ "slackware" +
104
+ self.arch +
105
+ "-" +
106
+ self.version +
107
+ "/"
108
+ s
86
109
  end
87
110
  }.compact
88
111
  }
@@ -33,7 +33,15 @@ module Slackware
33
33
  end
34
34
 
35
35
  def self::tags_used
36
- return installed_packages.map {|p| p.tag }.uniq.compact
36
+ pkgs = installed_packages
37
+ set = []
38
+ pkgs.map {|p| p.tag }.uniq.each {|tag|
39
+ m_set = {}
40
+ m_set[:tag] = tag
41
+ m_set[:count] = pkgs.map {|p| p if p.tag == tag }.compact.count
42
+ set << m_set
43
+ }
44
+ return set
37
45
  end
38
46
 
39
47
  def self::with_tag(tag)
@@ -142,7 +142,11 @@ def find_orphaned_config_files
142
142
  # build a list of config files currently installed
143
143
  installed_config_files = Slackware::System.installed_packages.map {|pkg|
144
144
  pkg.get_owned_files.map {|file|
145
- file if (file =~ /^etc\// && not(file =~ /\/$/))
145
+ if not(file =~ /\/$/)
146
+ if (file =~ /^etc\//)
147
+ file
148
+ end
149
+ end
146
150
  }
147
151
  }.flatten.compact
148
152
 
@@ -155,8 +159,10 @@ def find_orphaned_config_files
155
159
  if (config.count > 0)
156
160
  # remove config files that are owned by a currently installed package
157
161
  config = config.map {|file|
158
- if (not(installed_config_files.include?(file)) && not(installed_config_files.include?(file + ".new")))
159
- file
162
+ if not(installed_config_files.include?(file))
163
+ if not(installed_config_files.include?(file + ".new"))
164
+ file
165
+ end
160
166
  end
161
167
  }.compact
162
168
  # check again, and continue if there are no config files left
@@ -7,6 +7,6 @@ module Slackware
7
7
  rescue
8
8
  nil
9
9
  end
10
- UTILS_VERSION = "0.5.3"
10
+ UTILS_VERSION = "0.6.0"
11
11
  end
12
12
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack-utils
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 3
10
- version: 0.5.3
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Vincent Batts
@@ -48,6 +48,8 @@ files:
48
48
  - examples/repo.rb
49
49
  - lib/slackware.rb
50
50
  - lib/slackware/utils.rb
51
+ - lib/slackware/changelog.rb
52
+ - lib/slackware/changelog/rss.rb
51
53
  - lib/slackware/package.rb
52
54
  - lib/slackware/repo.rb
53
55
  - lib/slackware/version.rb
@@ -61,7 +63,7 @@ rdoc_options:
61
63
  - --main=README.rdoc
62
64
  - --line-numbers
63
65
  - --inline-source
64
- - --title=Slackware utils (slack-utils) 0.5.3 Documentation
66
+ - --title=Slackware utils (slack-utils) 0.6.0 Documentation
65
67
  require_paths:
66
68
  - lib
67
69
  required_ruby_version: !ruby/object:Gem::Requirement