#!/usr/bin/env ruby # -*- ruby -*- # # Copyright (c) 2000-2004 Akinori MUSHA # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # MYREVISION = %w$Rev$[1] MYDATE = %w$Date$[1] MYNAME = File.basename($0) require "optparse" require 'pkgtools' BROWSER = ENV['BROWSER'] || 'w3m:lynx:links:mozilla:netscape' CVSWEB_URI = { 'FreeBSD' => 'http://www.FreeBSD.org/cgi/cvsweb.cgi/', 'NetBSD' => 'http://cvsweb.netbsd.org/bsdweb.cgi/', 'OpenBSD' => 'http://www.openbsd.org/cgi-bin/cvsweb/', } CVSTAGS = CVSWEB_URI.keys CVSTAG_RE = /\$(#{CVSTAGS.join('|')}):\s+(\S+),v\s*(\d[\d.]*)/ MAKEFILE = 'Makefile' COLUMNSIZE = 24 NEXTLINE = "\n%*s" % [5 + COLUMNSIZE, ''] def init_global $tag = nil $path = nil $anchor = nil $file = nil end def main(argv) usage = <<-"EOF" usage: #{MYNAME} [-hqv] {pkgname_glob|portorigin_glob|file|directory} EOF banner = <<-"EOF" #{MYNAME} rev.#{MYREVISION} (#{MYDATE}) #{usage} EOF dry_parse = true OptionParser.new(banner, COLUMNSIZE) do |opts| opts.def_option("-h", "--help", "Show this message") { print opts exit 0 } opts.def_option("-q", "--noconfig", "Do not read pkgtools.conf") { |$noconfig| } opts.def_option("-v", "--verbose", "Be verbose") { |$verbose| } begin init_global rest = opts.order(*argv) unless $noconfig init_global load_config else argv = rest end dry_parse = false opts.order!(argv) rescue OptionParser::ParseError => e STDERR.puts "#{MYNAME}: #{e}", usage exit 64 end end file = $file = argv[0] || '.' retried = false loop do if File.directory?($file) $file = File.expand_path($file) Dir.chdir($file) $file = nil break elsif File.exist?($file) $file = File.expand_path($file) dir, $file = File.split(File.expand_path($file)) Dir.chdir(dir) break elsif retried puts "Inquiring the CVSweb site..." if $verbose uri = CVSWEB_URI['FreeBSD'] + file.sub(/^\//, '') open_browser(uri) puts "Inquiring the CVSweb site (ports)..." if $verbose uri = CVSWEB_URI['FreeBSD'] + File.join('ports', file) open_browser(uri) break else retried = true # search pkgdb if pattern = $pkgdb.strip($file) begin pattern = parse_pattern($file) puts "Searching pkgdb..." if $verbose if pkg = $pkgdb.glob(pattern)[0] puts "Inquiring the CVSweb site (ports)..." if $verbose uri = CVSWEB_URI['FreeBSD'] + File.join('ports', pkg.origin) open_browser(uri) # fall through end rescue RegexpError => e # warning_message e.message.capitalize end end # search portsdb pattern = $portsdb.strip($file) || $file # allow pkgname_glob begin pattern = parse_pattern(pattern) rescue RegexpError => e # warning_message e.message.capitalize next end puts "Searching portsdb..." if $verbose if port = $portsdb.glob(pattern)[0] $file = File.join($ports_dir, port.origin) next end end end if $file && !File.file?($file) STDERR.puts "#{MYNAME}: #{file}: not found." exit 1 end check_cvs() if $file if $tag.nil? || $path.nil? check_file($file, true) || check_makefile end else check_makefile end if $path.nil? dir, rel = File.split(Dir.pwd) until dir == '/' Dir.chdir(dir) check_makefile(rel) and break dir, last = File.split(dir) rel = File.join(last, rel) end if $path.nil? open_browser!(CVSWEB_URI['FreeBSD'] + file.sub(/^\//, '')) end end if $tag.nil? $tag = guess_tag(Dir.pwd) || guess_tag(RUBY_PLATFORM) || 'FreeBSD' end uri = CVSWEB_URI[$tag] + $path + ($anchor || '') open_browser!(uri) rescue => e STDERR.puts e.message exit 1 end def open_browser(uri) if uri_exist?(uri) open_browser!(uri) end end def open_browser!(uri) BROWSER.split(':').each do |s| s.strip! next if s.empty? s << ' %s' if not s.include?('%s') system('/bin/sh', '-c', format(s, uri)) and exit 0 end STDERR.puts 'No browser is available - please define BROWSER.' exit 1 end def check_cvs File.directory?('CVS') or return pwd = Dir.pwd if $verbose open('CVS/Repository') do |f| puts "Reading #{pwd}/CVS/Repository..." if $verbose $path = File.join(f.gets.chomp, $file || '') end rescue nil open('CVS/Root') do |f| puts "Reading #{pwd}/CVS/Root..." if $verbose $tag = guess_tag(f.gets) end rescue nil if $file open('CVS/Entries') do |f| puts "Reading #{pwd}/CVS/Entries..." if $verbose f.each do |line| ary = line.split('/') if ary[1] == $file $anchor = '#rev' + ary[2] break end end end rescue nil end end def check_makefile(subdir = nil) ret = check_file(MAKEFILE) if $path if subdir $path = File.join(File.dirname($path), subdir, $file || '') else $path = File.join(File.dirname($path), $file || '') end $anchor = nil if $file.nil? end ret end def check_file(file, set_anchor = false) IO::popen("/usr/bin/ident #{file} 2>/dev/null").each do |line| puts "Checking ident of #{file}..." if $verbose if CVSTAG_RE =~ line $tag = $1 $anchor = '#rev' + $3 if set_anchor if $path.nil? case $tag when 'NetBSD' if %r:/([^/]+/[^/]+)$: =~ Dir.pwd $path = File.join('pkgsrc', $1, file) end when 'OpenBSD' category = `make -V CATEGORIES`.split[0] if %r"/(#{Regexp.quote(category)}(?:/[^/]+){1,3})$" =~ Dir.pwd $path = File.join('ports', $1, file) end else $path = $2 end break end end end true rescue return false end def guess_tag(hint) CVSTAGS.each do |name| if /#{name}/i =~ hint return name end end nil end def uri_exist?(uri) if system('/usr/bin/fetch', '-qs', uri) return true else return false end end main(ARGV)