Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Mar 2010 12:29:22 +1100
From:      thoran <null@thoran.com>
To:        FreeBSD GNOME Team <gnome@FreeBSD.org>
Subject:   /usr/ports/UPDATING Suggestions and Script
Message-ID:  <9DF5B3BA-FDE9-4062-AACC-9AB05DB9DC2A@thoran.com>

next in thread | raw e-mail | index | archive | help
Hi,

I found your email address in /usr/ports/UPDATING.  I am emailing you  
because you are one of a number of people who make entries into this  
file and as such may have some control over either the formatting  
conventions of /usr/ports/UPDATING or how well such conventions are  
adhered to.

The reason I care is because I have the intention of parsing /usr/ 
ports/UPDATING with a view to comparing those ports noted in /usr/ 
ports/UPDATING with a list of the installed ports, rather than having  
to look at everything in that very long file.  (Note that this is no  
longer an intention, since I just wrote something to do this.  See  
below...)

I understand that the instructions for /usr/ports/UPDATING are for it  
to be "read", but given it's length it might be easier to be able to  
check this file against installed ports automatically in the first  
instance.

Already I have found cat UPDATING | grep AFFECTS: to be handy, but an  
automated process (possibly including a cron?) to parse this and do  
the matching with installed ports automatically is surely a save.   
Does anyone agree?

However, if this is to be done, then may I suggest the following...

1. On the AFFECTS: line only use a list of affected ports and nothing  
else, ie.

AFFECTS: category/port
AFFECTS: category/port, category/port

2. When there is a list of ports and that list is quite long, it may  
be simpler to make reference to a meta port and exclude some specific  
known ports which are in the meta package, but are not affected, ie.

AFFECTS: category/meta-port, [category/port, category/port]

3. On the AFFECTS: line put the version of the port(s) affected, ie.

AFFECTS: category/port-x.y.z
AFFECTS: category/port-x.y.z, category/port-a.b.c

That way checks against the installed ports for specific versions can  
be made to ensure relevancy.

4. Alternately, either have the version number in the AFFECTS: line as  
per 3. above, or have the date of the particular version of a port  
readily accessible, so as relevancy can be checked by date rather than  
by version.  Version numbers are preferred however.

5. On the AFFECTS: line, please don't do this (no category/port format):

AFFECTS: all ports using libtool as part of the build process
AFFECTS: ports that use Display Postscript libraries and xorg-libraries

5. Also please don't do this (no AUTHOR: line):

20051002:
AFFECTS: users of x11-toolkits/py-wxPython26

6. Somewhat unimportantly, on the AUTHOR: line, please don't do this:

AUTHOR: ahze@FreeBSD.org and the FreeBSD GNOME team

Rather have an email address only, or a mailing list or alias address.

And after all that, so as to not be merely an irritating troll, here's  
a first go tonight at a script to do some automation of the check  
against installed ports below...

Lastly, I imagine a fair proportion of the older email addresses will  
bounce, so I'm putting null@thoran.com as the from address.  I haven't  
put this up there yet, but try me at github instead.

Thanks,


thoran

#!/usr/bin/env ruby
# check_ports_updating

# 2010.03.26
# 0.3.0

# Description: This checks the /usr/ports/UPDATING file for matching  
installed ports and outputs any entries for the last year.

# Copyright: (c) 2010, thoran. All rights reserved.

# Licence: Either Ruby's or the current 2-clause FreeBSD as you wish.

# Notes: This restricts output of matching ports to the last year of  
notices, since I expect they are likely to be the most relevant.

require 'date'

class Array

alias_method :last!, :pop

def all_but_last
d = self.dup
d.last!
d
end

end

class Date

def self.last_year
begin
new(today.year, 2, 29)
new(today.year - 1, today.month, today.mday - 1)
rescue
new(today.year - 1, today.month, today.mday)
end
end

def self.parse(s, day_first = false)
require 'parsedate'
if day_first
a = ParseDate.parsedate(s).compact
a = [a[0], a[2], a[1]]
Date.new(*a)
else # assume day_second, and otherwise make best guess
begin
a = ParseDate.parsedate(s).compact
Date.new(*a)
rescue
a = [a[0], a[2], a[1]]
Date.new(*a)
end
end
end

end

class String

def last_char
self[self.length - 1, 1]
end

def last_char!
s = self[self.length - 1, 1]
chop!
s
end

def munch
while self.last_char == "\n"
self.last_char!
end
self
end

def lmunch
self.reverse.munch.reverse
end

end

class InstalledPorts
class << self

def list
pkg_info_bin = `which pkg_info`.chomp
raw_port_list = `#{pkg_info_bin} -ao`
raw_port_list.split("\n").inject([]){|a,line| a << line.match(/for  
(.*):$/)[1] if line =~ /^Information/; a}
end

def list_without_version
list.collect{|e| e.split('-').all_but_last.join}
end

end
end

class PortsUpdatingItem

def initialize(item)
@item = item
end

def affects
md = @item.match(/^  AFFECTS: (.*$)/)
md[1] if md
end

def author
md = @item.match(/^  AUTHOR: (.*$)/)
md[1] if md
end

def date
md = @item.match(/^(\d\d\d\d\d\d\d\d):$/)
md[1] if md
end

def description
@item.gsub(/^  AFFECTS: .*$/, '').gsub(/^  AUTHOR: .*$/, '').gsub(/^\d 
\d\d\d\d\d\d\d:$/, '')
end

end

class PortsUpdatingFile
class << self

def parse(filename = nil)
filename ||= '/usr/ports/UPDATING'
item = ''
updating_items = []
File.read(filename).each do |line|
if line =~ /^\d\d\d\d\d\d\d\d:$/
  updating_items << PortsUpdatingItem.new(item)
  item = line
else
  item = item + line
end
end
updating_items.shift
updating_items
end

end
end

class PortsUpdating
class << self

def check(filename = nil)
matches = []
InstalledPorts.list_without_version.each do |port|
PortsUpdatingFile.parse(filename).each do |item|
  if item.affects =~ /#{port}/
    if Date.parse(item.date) > Date.last_year
      matches << {:port => port, :date => item.date, :affects =>  
item.affects, :author => item.author, :description => item.description}
    end
  end
end
end
show_results(matches)
end

def show_results(matches)
puts
m = matches.sort{|a,b| a[:port] <=> b[:port]}
m.each do |e|
puts "PORT: #{e[:port]}"
puts "DATE: #{e[:date]}"
puts "AFFECTS: #{e[:affects]}"
puts "AUTHOR: #{e[:author]}"
puts "DESCRIPTION: \n#{e[:description].lmunch}"
puts
end
puts
puts "Overview of Affected Installed Ports:"
puts
m = matches.sort{|a,b| a[:date] <=> b[:date]}
m.each{|e| puts "    #{e[:date]}, #{e[:port]}"}
puts
end

end
end

if __FILE__ == $0
PortsUpdating.check(ARGV[0])
end




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9DF5B3BA-FDE9-4062-AACC-9AB05DB9DC2A>