aboutsummaryrefslogtreecommitdiff
path: root/src/etcat
diff options
context:
space:
mode:
authorfuzzyray <fuzzyray@gentoo.org>2009-04-30 21:52:45 +0000
committerfuzzyray <fuzzyray@gentoo.org>2009-04-30 21:52:45 +0000
commit86eaf5e03289e45a95514b4f6011157972016e9d (patch)
treec16903693f2030c7b01b346b29b265dc1a473888 /src/etcat
parentFix has_key() deprecation message. (Bug #232797) (diff)
downloadgentoolkit-0.2.4.tar.gz
gentoolkit-0.2.4.tar.bz2
gentoolkit-0.2.4.zip
Tagging the gentoolkit-0.2.4 releasegentoolkit-0.2.4
svn path=/tags/gentoolkit-0.2.4/; revision=564
Diffstat (limited to 'src/etcat')
-rw-r--r--src/etcat/AUTHORS5
-rw-r--r--src/etcat/ChangeLog36
-rw-r--r--src/etcat/Makefile18
-rw-r--r--src/etcat/README2
-rw-r--r--src/etcat/TODO0
-rwxr-xr-xsrc/etcat/etcat688
-rw-r--r--src/etcat/etcat.179
7 files changed, 828 insertions, 0 deletions
diff --git a/src/etcat/AUTHORS b/src/etcat/AUTHORS
new file mode 100644
index 0000000..5da0b07
--- /dev/null
+++ b/src/etcat/AUTHORS
@@ -0,0 +1,5 @@
+Maintainer:
+Karl Trygve Kalleberg <karltk@gentoo.org>
+
+Authors:
+Alastair Tse <liquidx@gentoo.org> (original author)
diff --git a/src/etcat/ChangeLog b/src/etcat/ChangeLog
new file mode 100644
index 0000000..bdadcb6
--- /dev/null
+++ b/src/etcat/ChangeLog
@@ -0,0 +1,36 @@
+2004-04-20 Marius Mauch <genone@gentoo.org>
+ - fixing -u behavior so it matches equery (bug #47690)
+
+2004-03-13 Marius Mauch <genone@gentoo.org>
+ - grouping version in --version output
+
+2004-01-23 Marius Mauch <genone@gentoo.org>
+ - now catches exceptions thrown by portage
+ - minor bugfixes
+
+2004-01-07 Karl Trygve Kalleberg <karltk@gentoo.org>
+ * Added man page from app-portage/gentoolkit
+ * Added Makefile
+ * Added sys.path workaround for Portage >=2.0.50
+
+* etcat-0.2.0 (06 May 2003)
+ 06 May 2003; Alastair Tse <liquidx@gentoo.org>
+ Trying to add a dependency graph feature. kind of works with
+ some weird hacks parsing the depenency string. probably needs
+ to use functions in portage to parse it properly.
+
+* etcat-0.1.4 (27 Apr 2003)
+
+ 27 Apr 2003; Alastair Tse <liquidx@gentoo.org>
+ Added "files", "belongs", "depends" functions.
+
+*etcat-0.1.3 (24 Apr 2003)
+
+ 24 Apr 2003; Alastair Tse <liquidx@gentoo.org>
+ Fixed bug if ebuild doesn't exist. Added manpage.
+
+*etcat-0.1.2 (29 Mar 2003)
+
+ 29 Mar 2003; Alastair Tse <liquidx@gentoo.org>
+ Initial commit to gentoolkit. Check source for previous changes
+
diff --git a/src/etcat/Makefile b/src/etcat/Makefile
new file mode 100644
index 0000000..2281646
--- /dev/null
+++ b/src/etcat/Makefile
@@ -0,0 +1,18 @@
+# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org>
+# Copyright 2004 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header$
+
+include ../../makedefs.mak
+
+all:
+
+dist:
+ mkdir -p ../../$(distdir)/src/etcat
+ cp Makefile AUTHORS README TODO ChangeLog etcat etcat.1 ../../$(distdir)/src/etcat
+
+install:
+ install -d $(docdir)/deprecated/etcat
+ install -m 0755 etcat $(docdir)/deprecated/etcat/
+ install -m 0644 etcat.1 README AUTHORS $(docdir)/deprecated/etcat/
diff --git a/src/etcat/README b/src/etcat/README
new file mode 100644
index 0000000..50bd2f3
--- /dev/null
+++ b/src/etcat/README
@@ -0,0 +1,2 @@
+For more information, this tool was originally hosted on:
+http://www.liquidx.net/projects/etcat/
diff --git a/src/etcat/TODO b/src/etcat/TODO
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/etcat/TODO
diff --git a/src/etcat/etcat b/src/etcat/etcat
new file mode 100755
index 0000000..5137683
--- /dev/null
+++ b/src/etcat/etcat
@@ -0,0 +1,688 @@
+#!/usr/bin/env python2
+#
+# -*- mode: python; -*-
+#
+# --| Version Information |------------------------------------------
+#
+# etcat v0.1.4 (27 Apr 2003)
+#
+# $Header$
+#
+# --| About |--------------------------------------------------------
+#
+# etcat is a Portage/Ebuild Information Extractor. Basically, it
+# provides higher level convienence functions to the Portage system
+# used by Gentoo Linux.
+#
+# You can use it to quickly find out the recent changes of your
+# favourite package, the size of installed packages, the
+# available versions for a package and more.
+#
+# --| License |------------------------------------------------------
+#
+# Distributed under the terms of the GNU General Public License v2
+# Copyright (c) 2002 Alastair Tse.
+#
+# --| Usage |--------------------------------------------------------
+#
+# etcat [options] <command> <package[-ver]|ebuild|category/package[-ver]>
+#
+# -b/belongs ) checks what package(s) a file belongs to
+# -c/changes ) list the more recent changelog entry
+# -d/depends ) list all those that have this in their depends
+# -f/files ) list all files that belong to this package
+# -g/graph ) graph dependencies
+# -s/size ) guesses the size of a installed packaged.
+# -u/uses ) list all the use variables used in this package/ebuild
+# -v/versions ) list all the versions available for a package
+#
+# --| TODO |---------------------------------------------------------
+#
+# - in ver_cmp: 1.2.10a < 1.2.10, need to fix that
+#
+# --| Changes |------------------------------------------------------
+#
+# * etcat-0.3.1 (10 Oct 2004) [karltk]
+# - Fixed changes help examples
+# * etcat-0.3.1 (08 Jan 2004) [genone]
+# - adding missing python searchpath modification
+# - fixing sort order
+# * etcat-0.3.0 (12 Jul 2003) [karltk]
+# - Refactored interesting stuff into the Gentoolkit module
+# * etcat-0.2.0 (13 Jun 2003)
+# - Updated "versions" with PORTAGE_OVERLAY detection
+# - Added "graph" feature
+# * etcat-0.1.5 (30 Apr 2003)
+# - Fixed disappearing short opts. Oops.
+# * etcat-0.1.4 (27 Apr 2003)
+# - Cleaned up command execution code to provide a single place
+# to specify functions
+# - Added own custom wrapping print code.
+# - Added "files" feature
+# - Added "depends" feature
+# * etcat-0.1.3 (24 Apr 2003)
+# - Overhaul of commandline interpreter
+# - Added "belongs" feature
+# - Reimplemented "uses" to deal with IUSE more cleanly
+# and sources use.local.desc
+# - Natural Order Listings for version
+# * etcat-0.1.2 (29 Mar 2003)
+# - Added unstable indicator to complement masked
+# - improved use flag listing
+# * etcat-0.1.1 (21 Jan 2003)
+# - Add package to versions listing even if it's not in
+# the portage anymore (21 Jan 2003)
+# - Fixed old ehack references (17 Jan 2003)
+# * etcat-0.1 (31 Oct 2002)
+# Initial Release;
+#
+# -------------------------------------------------------------------
+
+
+
+import os
+import sys
+import re
+import pprint
+import getopt
+import glob
+
+# portage and gentoolkit need special path modifications
+sys.path.insert(0, "/usr/lib/portage/pym")
+sys.path.insert(0, "/usr/lib/gentoolkit/pym")
+
+import gentoolkit
+from stat import *
+try:
+ from portage.output import *
+except ImportError:
+ from output import *
+
+__author__ = "Alastair Tse"
+__email__ = "liquidx@gentoo.org"
+__version__ = "0.3.1"
+__productname__ = "etcat"
+__description__ = "Portage Information Extractor"
+
+# .-------------------------------------------------------.
+# | Initialise Colour Settings |
+# `-------------------------------------------------------'
+if (not sys.stdout.isatty()) or (gentoolkit.settings["NOCOLOR"] in ["yes","true"]):
+ nocolor()
+
+# "option": ("shortcommand","desc",["example one", "example two"])
+options = {
+"belongs": \
+("b","Searches for a package that owns a specified file with an option to restrict the search space.",
+["etcat belongs /usr/bin/gimp media-gfx",
+ "etcat belongs /usr/lib/libjpeg.so media-*",
+ "etcat belongs /usr/lib/libmpeg.so"]),
+"changes": \
+("c","Outputs the changelog entry to screen. It is possible to give a version number along with the package name.",
+["etcat changes mozilla",
+ "etcat changes =mozilla-1.1-r1",
+ "etcat changes gkrellm$"]),
+"depends": \
+("d","Finds all packages that are directly dependent to a regex search string.",
+["etcat depends 'gnome-base/libgnome'",
+ "etcat depends '>=dev-lang/python-2.2'"]),
+"files": \
+("f","Lists files that belongs to a package and optionally with version.",[]),
+"graph": \
+("g","Graphs Dependencies (NON WORKING)",[]),
+"size": \
+("s","Lists the installed size of a package.",[]),
+"uses": \
+("u", "Advanced output of USE vars in a package. Tells you flags used by a package at time of installation, flags in current config and flag description.",[]),
+"versions": \
+("v","Displays the versions available for a specific package. Colour coded to indicate installation status and displays slot information.",
+[turquoise("(I)") + "nstalled",
+ yellow("(~)") + "Unstable Testing Branch",
+ red("(M)") + "asked Package"])
+}
+
+# .-------------------------------------------------------.
+# | Small Wrapping Printer with Indent Support |
+# `-------------------------------------------------------'
+
+def wrap_print(string, indent=0, width=74):
+ line_len = width - indent
+ str_len = len(string)
+ lines = []
+
+ pos = 0
+ thisline = ""
+ while pos < str_len:
+ # if we still have space stuff the
+ # character in this line
+ if len(thisline) < line_len-1:
+ thisline += string[pos]
+ pos += 1
+ # if we're at the end of the line,
+ # check if we should hyphenate or
+ # append
+ elif len(thisline) == line_len -1:
+ # end of a text
+ if pos == str_len -1:
+ thisline += string[pos]
+ pos += 1
+ # end of a word
+ elif string[pos] != " " and string[pos+1] == " ":
+ thisline += string[pos]
+ pos += 1
+ # just a space
+ elif string[pos] == " ":
+ thisline += string[pos]
+ pos += 1
+ # start of a word, we start the word on the next line
+ elif pos>0 and string[pos-1] == " ":
+ thisline += " "
+ # needs hyphenating
+ else:
+ thisline += "-"
+
+ # append the line
+ lines.append(thisline)
+ thisline = ""
+
+ # append last line
+ if thisline:
+ lines.append(thisline)
+
+ for line in lines:
+ print " "*indent + line
+
+# +-------------------------------------------------------+
+# | Pretty Print Log |
+# +-------------------------------------------------------+
+# | Extracts and prints out the log entry corresponding |
+# | to a certain revision if given. If not supplied, |
+# | prints out the latest/topmost entry |
+# `-------------------------------------------------------'
+
+# output the latest entry in changelog
+def output_log(lines, package_ver=""):
+ # using simple rules that all changelog entries have a "*"
+ # as the first char
+ is_log = 0
+ is_printed = 0
+
+ for line in lines:
+ if package_ver:
+ start_entry = re.search("^[\s]*\*[\s]*(" + package_ver + ")[\s]+.*(\(.*\))",line)
+ else:
+ start_entry = re.search("^[\s]*\*[\s]*(.*)[\s]+.*(\(.*\))",line)
+ if not is_log and start_entry:
+ is_printed = 1
+ is_log = 1
+ print green("*") + " " + white(start_entry.group(1)) + " " + turquoise(start_entry.group(2)) + " :"
+ elif is_log and re.search("^[\s]*\*[\s]*(.*)[\s]+.*(\(.*\))",line):
+ break
+ elif is_log:
+ print line.rstrip()
+ else:
+ pass
+
+ return is_printed
+
+# .-------------------------------------------------------.
+# | Changes Function |
+# +-------------------------------------------------------+
+# | Print out the ChangeLog entry for package[-version] |
+# `-------------------------------------------------------'
+
+def changes(query, matches):
+ if not report_matches(query,matches,installed_only=0):
+ return
+
+ for pkg in matches:
+ changelog_file = pkg.get_package_path() + "/ChangeLog"
+ if os.path.exists(changelog_file):
+ output_log(open(changelog_file).readlines(), pkg.get_name()+"-"+pkg.get_version())
+ else:
+ print red("Error") + ": No Changelog for " + pkg.get_cpv()
+
+
+# .-------------------------------------------------------.
+# | Versions Function |
+# +-------------------------------------------------------+
+# | Prints out the available version, masked status and |
+# | installed status. |
+# `-------------------------------------------------------'
+
+def versions(query, matches):
+ # this function should also report masked packages
+ matches = gentoolkit.find_packages(query, masked=True)
+ if not report_matches(query,matches):
+ return
+
+ # sorting result list
+ matches = gentoolkit.sort_package_list(matches)
+
+ # FIXME: old version printed result of regex search on name,
+ # so "ant" would return app-emacs/semantic, etc...
+
+ last_cp = ""
+
+ for pkg in matches:
+ new_cp = pkg.get_category()+"/"+pkg.get_name()
+ if last_cp != new_cp:
+ print green("*") + " " + white(new_cp) + " :"
+ last_cp = new_cp
+
+ state = []
+ color = green
+ unstable = 0
+ overlay = ""
+
+ # check if masked
+ if pkg.is_masked():
+ state.append(red("M"))
+ color = red
+ else:
+ state.append(" ")
+
+ # check if in unstable
+ kwd = pkg.get_env_var("KEYWORDS")
+ if "~" + gentoolkit.settings["ARCH"] in kwd.split():
+ state.append(yellow("~"))
+ if color != red:
+ color = yellow
+ unstable = 1
+ else:
+ state.append(" ")
+
+ # check if installed
+ if pkg.is_installed():
+ state.append(turquoise("I"))
+ color = turquoise
+ else:
+ state.append(" ")
+
+ # check if this is a OVERLAY ebuilds
+ if pkg.is_overlay():
+ overlay = " OVERLAY"
+
+ ver = pkg.get_version()
+ slot = pkg.get_env_var("SLOT")
+ print " "*8 + "[" + "".join(state) + "] " + color(ver) + " (" + color(slot) + ")" + overlay
+
+# .-------------------------------------------------------.
+# | List USE flags for a single ebuild, if it's installed |
+# +-------------------------------------------------------+
+# | Just uses the new IUSE parameter in ebuilds |
+# `-------------------------------------------------------'
+def uses(query, matches):
+ useflags = gentoolkit.settings["USE"].split()
+ usedesc = {}
+ uselocaldesc = {}
+
+ # Load global USE flag descriptions
+ try:
+ fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc")
+ usedesc = {}
+ for line in fd.readlines():
+ if line[0] == "#":
+ continue
+ fields = line.split(" - ")
+ if len(fields) == 2:
+ usedesc[fields[0].strip()] = fields[1].strip()
+ except IOError:
+ pass
+
+ # Load local USE flag descriptions
+ try:
+ fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc")
+ for line in fd.readlines():
+ if line[0] == "#":
+ continue
+ fields = line.split(" - ")
+ if len(fields) == 2:
+ catpkguse = re.search("([a-z]+-[a-z]+/.*):(.*)", fields[0])
+ if catpkguse:
+ if not uselocaldesc.has_key(catpkguse.group(1).strip()):
+ uselocaldesc[catpkguse.group(1).strip()] = {catpkguse.group(2).strip() : fields[1].strip()}
+ else:
+ uselocaldesc[catpkguse.group(1).strip()][catpkguse.group(2).strip()] = fields[1].strip()
+ except IOError:
+ pass
+
+ print "[ Colour Code : " + green("set") + " " + red("unset") + " ]"
+ print "[ Legend : (U) Col 1 - Current USE flags ]"
+ print "[ : (I) Col 2 - Installed With USE flags ]"
+
+ if filter(gentoolkit.Package.is_installed, matches):
+ only_installed = True
+ else:
+ only_installed = False
+
+ # Iterate through matches, printing a report for each package
+ for p in matches:
+ if not p.is_installed() and only_installed:
+ continue
+
+ bestver = p.get_cpv()
+ iuse = p.get_env_var("IUSE")
+
+ if iuse: usevar = iuse.split()
+ else: usevar = []
+
+ inuse = []
+ used = p.get_use_flags().split()
+
+ # store (inuse, inused, flag, desc)
+ output = []
+
+ for u in usevar:
+ inuse = 0
+ inused = 0
+ try:
+ desc = usedesc[u]
+ except KeyError:
+ try:
+ desc = uselocaldesc[p.get_category()+"/"+p.get_name()][u]
+ except KeyError:
+ desc = ""
+
+ if u in p.get_settings("USE"): inuse = 1
+ if u in used: inused = 1
+
+ output.append((inuse, inused, u, desc))
+
+ # pretty print
+ if output:
+ print
+ print white(" U I ") + "[ Found these USE variables in : " + white(bestver) + " ]"
+ maxflag_len = 0
+ for inuse, inused, u, desc in output:
+ if len(u) > maxflag_len:
+ maxflag_len = len(u)
+
+ for inuse, inused, u, desc in output:
+ flag = ["-","+"]
+ colour = [red, green]
+ if inuse != inused:
+ print yellow(" %s %s" % (flag[inuse], flag[inused])),
+ else:
+ print " %s %s" % (flag[inuse], flag[inused]),
+
+ print colour[inuse](u.ljust(maxflag_len)),
+
+ # print description
+ if desc:
+ print ":", desc
+ else:
+ print ": unknown"
+ else:
+ print "[ No USE flags found for :", white(p.get_cpv()), "]"
+
+ return
+
+# .-------------------------------------------------------.
+# | Graphs the Dependency Tree for a package |
+# +-------------------------------------------------------+
+# | Naive graphing of dependencies
+# `-------------------------------------------------------'
+
+def graph(query, matches):
+ if not report_matches(query, matches):
+ return
+
+ for pkg in matches:
+ if not pkg.is_installed():
+ continue
+ rgraph(pkg)
+
+def rgraph(pkg,level=0,pkgtbl=[],suffix=""):
+
+ cpv=pkg.get_cpv()
+
+ print level*" " + "`-- " + cpv + suffix
+ pkgtbl.append(cpv)
+
+ for x in pkg.get_runtime_deps():
+ suffix=""
+ cpv=x[2]
+ pkg=gentoolkit.find_best_match(x[0] + cpv)
+ if not pkg:
+ continue
+ if pkg.get_cpv() in pkgtbl:
+ continue
+ if cpv.find("virtual")==0:
+ suffix+=" (" + cpv + ")"
+ if len(x[1]):
+ suffix+=" [ " + "".join(x[1]) + " ]"
+ pkgtbl=rgraph(pkg,level+1,pkgtbl,suffix)
+ return pkgtbl
+
+# .-------------------------------------------------------.
+# | Required By Function |
+# +-------------------------------------------------------+
+# | Find what packages require a given package name |
+# `-------------------------------------------------------'
+
+def depends(query, matches):
+
+ print "[ Results for search key : " + white(query) + " ]"
+
+ isdepend = gentoolkit.split_package_name(query)
+
+ for pkg in matches:
+ if pkg.is_installed():
+ deps = pkg.get_runtime_deps()
+ for x in deps:
+ cpvs=gentoolkit.split_package_name(x[2])
+ cat_match=0
+ ver_match=0
+ name_match=0
+ if not isdepend[0] or isdepend[0] == cpvs[0]:
+ cat_match=1
+ if not isdepend[2] or \
+ (isdepend[2] == cpvs[2] and isdepend[3] == cpvs[3]):
+ ver_match=1
+ if isdepend[1] == cpvs[1]:
+ name_match=1
+ if cat_match and ver_match and name_match:
+ print turquoise("*"), white(pkg.get_cpv()), white("[ ") + "".join(x[1]), white("]")
+
+# .-------------------------------------------------------.
+# | Belongs to which package |
+# +-------------------------------------------------------+
+# | Finds what package a file belongs to |
+# `-------------------------------------------------------'
+
+def belongs(query,matches):
+
+ q = query.split()
+
+ if len(q) > 1:
+ item=q[0]
+ cat=q[1]
+ fn=lambda x: x.find(cat)==0
+ else:
+ item=q[0]
+ cat="*"
+ fn=None
+ matches = gentoolkit.find_all_installed_packages(fn)
+
+ print "Searching for " + item + " in " + cat + " ..."
+
+ rx = re.compile(item)
+
+ for pkg in matches:
+ if pkg.get_contents():
+ for fn in pkg.get_contents().keys():
+ if rx.search(fn):
+ print pkg.get_cpv()
+ break # We know this pkg matches, look for any more matches
+ return
+
+# .-------------------------------------------------------.
+# | Size of all packages matching query |
+# +-------------------------------------------------------+
+# | Finds the size of installed packages |
+# `-------------------------------------------------------'
+def size(query,packages):
+ packages = gentoolkit.find_packages(query)
+ if not report_matches(query, packages):
+ return
+
+ for pkg in packages:
+ if not pkg.is_installed():
+ continue
+ x=pkg.size()
+ size=x[0]
+ files=x[1]
+ uncounted=x[2]
+ print turquoise("*") + " " + white(pkg.get_cpv())
+ print " Total Files : ".rjust(25) + str(files)
+ if uncounted:
+ print " Inaccessible Files : ".rjust(25) + str(uncounted)
+ print " Total Size : ".rjust(25) + "%.2f KB" % (size/1024.0)
+
+
+def report_matches(query, matches, installed_only=1):
+ print "[ Results for search key : " + white(query) + " ]"
+ print "[ Candidate applications found : " + white(str(len(matches))) + " ]"
+ print
+
+ if installed_only and matches:
+ print " Only printing found installed programs."
+ print
+ elif installed_only:
+ print "No packages found."
+
+ if matches:
+ return 1
+ else:
+ return 0
+
+
+# .-------------------------------------------------------.
+# | Files in a package |
+# +-------------------------------------------------------+
+# | Lists all the files in a package |
+# `-------------------------------------------------------'
+def files(query,matches):
+ if not report_matches(query, matches):
+ return
+
+ for package in matches:
+ if not package.is_installed():
+ continue
+ contents = package.get_contents()
+
+ print yellow(" * ") + white(package.get_cpv())
+ for x in contents.keys():
+ t = contents[x][0]
+ if t == "obj":
+ print x
+ elif t == "sym":
+ print turquoise(x)
+ elif t == "dir":
+ print blue(x)
+ else:
+ print x
+
+# .-------------------------------------------------------.
+# | Help Function |
+# `-------------------------------------------------------'
+def ver():
+ print __productname__ + " (" + __version__ + ") - " + __description__ + " - By: " + __author__
+
+def help():
+ screenwidth = 74
+ margin = 2
+ margin_desc = 4
+ margin_ex = 8
+
+ ver()
+ print yellow("NOTICE: ") + "This tool will be phased out at some point in"
+ print " the future, please use equery instead."
+ print " Bugs are still fixed, but new features won't be added."
+ print
+ print white("Usage: ") + turquoise(__productname__) + " [ " + green("options") + " ] [ " + turquoise("action") + " ] [ " + turquoise("package") + " ]"
+ print
+ print turquoise("Actions:")
+ print
+ for name,tup in options.items():
+ print " "*margin + green(name) + " (" + green("-" + tup[0]) + " short option)"
+ wrap_print(tup[1],indent=margin_desc)
+ for example in tup[2]:
+ print " "*margin_ex + example
+ print
+
+# .-------------------------------------------------------.
+# | Main Function |
+# `-------------------------------------------------------'
+def main():
+
+ action = ''
+ query = ''
+
+ if len(sys.argv) < 3:
+ help()
+ sys.exit(1)
+
+ # delegates the commandline stuff to functions
+ pointer = 2
+ # short/long opts mapping
+ shortopts = ["-"+x[0] for x in options.values()]
+ short2long = {}
+ for k,v in options.items():
+ short2long[v[0]] = k
+ longopts = options.keys()
+ # loop thru arguments
+ for arg in sys.argv[1:]:
+ if arg[0] == "-" and len(arg) == 2 and arg in shortopts:
+ action = short2long[arg[1]]
+ query = ' '.join(sys.argv[pointer:])
+ break
+ elif arg in longopts:
+ action = arg
+ query = ' '.join(sys.argv[pointer:])
+ break
+ else:
+ pointer += 1
+
+ # abort if we don't have an action or query string
+ if not query or action not in options.keys():
+ help()
+ sys.exit(1)
+ else:
+ try:
+ matches = gentoolkit.find_packages(query)
+ except KeyError, e:
+ if e[0].find("Specific key requires operator") == 0:
+ print red("!!!"), "Invalid syntax: missing operator"
+ print red("!!!"), "If you want only specific versions please use one of"
+ print red("!!!"), "the following operators as prefix for the package name:"
+ print red("!!!"), " > >= = <= <"
+ print red("!!!"), "Example to only match gcc versions greater or equal 3.2:"
+ print red("!!!"), " >=sys-devel/gcc-3.2"
+ else:
+ print red("!!!"), "Internal portage error, terminating"
+ if len(e[0]):
+ print red("!!!"), e
+ sys.exit(2)
+ except ValueError, e:
+ if isinstance(e[0],list):
+ print red("!!!"), "Ambiguous package name \"%s\"" % query
+ print red("!!!"), "Please use one of the following long names:"
+ for p in e[0]:
+ print red("!!!"), " "+p
+ else:
+ print red("!!!"), "Internal portage error, terminating"
+ if len(e[0]):
+ print red("!!!"), e[0]
+ sys.exit(2)
+ function = globals()[action]
+ function(query, matches)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ print "Operation Aborted!"
+
+
diff --git a/src/etcat/etcat.1 b/src/etcat/etcat.1
new file mode 100644
index 0000000..6704f3b
--- /dev/null
+++ b/src/etcat/etcat.1
@@ -0,0 +1,79 @@
+.TH "etcat" "1" "0.1.4" "Alastair Tse <liquidx@gentoo.org>" "Gentoo Administration"
+.SH "NAME"
+.LP
+etcat \- Gentoo: Portage Information Extractor
+.SH "SYNTAX"
+.LP
+etcat [\fIoption\fP|command] <\fIquery|package\fP>
+
+.SH "DESCRIPTION"
+.LP
+etcat tries to complement the existing portage related tools but geared specifically for the power user. It enables users and developers to quickly find out information on particular packages without resorting to manually poking the portage tree and portage database.
+
+.LP
+More specifically, it lists the versions available highlighted by their status (stable/testing/masked/install) for a package, lists use flags per package with descriptions, calculates the installed size of a package and also outputs the relevent entries in the changelog related to the package version.
+
+.LP
+It also employes a smarter package query syntax than emerge where examples such as:
+.LP .IP
+mozilla\-1.1
+.br
+mozilla\-1.*
+.LP
+are accepted.
+
+.SH "OPTIONS"
+.LP
+\fB\-b\fR <\fI/path/to/file\fR> [\fIcategory\fR]
+.br
+\fBbelongs\fR <\fI/path/to/file\fR> [\fIcategory\fR]
+.IP
+Searches for the package which a file belongs to with an option to restrict a search to a single or multiple category. Wildcards in the category name is accepted to speed up searching. (eg. etcat belongs /usr/lib/libmpeg.so "media\-*")
+
+.LP
+\fB\-c\fR <\fIpackage[\-version]\fR>
+.br
+\fBchanges\fR <\fIpackage[\-version]\fR>
+.IP
+Outputs ChangeLog entry for the package and version specified. Uses the latest package version if none specified.
+
+.LP
+\fB\-d\fR <\fIregex expression\fR>
+.br
+\fBdepends\fR <\fIregex expression\fR>
+.IP
+Searches through portage for a dependency string satisfying that regular expression.
+
+.LP
+\fB\-f\fR <\fIpackage[\-version]\fR>
+.br
+\fBfiles\fR <\fIpackage[\-version]\fR>
+.IP
+Lists all the files installed for this package.
+
+.LP
+\fB\-s\fR <\fIpackage\fR>
+.br
+\fBsize\fR <\fIpackage\fR>
+.IP
+Outputs the installed size of the package.
+
+.LP
+\fB\-u\fR <\fIpackage[\-version]\fR>
+.br
+\fBuses\fR <\fIpackage[\-version]\fR>
+.IP
+Outputs the USE flags supported by this package and also their installed state and description.
+
+.LP
+\fB\-v\fR <\fIpackage\fR>
+.br
+\fBversions\fR <\fIpackage\fR>
+.IP
+Output all the versions for packages that match the \fIpackage\fR name given with indication of whether the packages is stable, masked, unstable or installed.
+.SH "SEE ALSO"
+.LP
+Type \fBetcat\fR for examples and more information
+.SH "AUTHORS"
+.LP
+Alastair Tse <liquidx@gentoo.org>