Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 1188 lines (1096 sloc) 46.298 kb
#!/usr/bin/env lua
package.cpath = "/home/kiwi/media/programs/lua/clyde/?.so;"..package.cpath
package.path ="/home/kiwi/media/programs/lua/clyde/?.lua;"..package.path
colorize = require "clydelib.colorize"
local util = require "clydelib.util"
local sync = require "clydelib.sync"
local query = require "clydelib.query"
local remove = require "clydelib.remove"
local upgrade = require "clydelib.upgrade"
local packages = require "clydelib.packages"
local alpm = require "lualpm"
local utilcore = require "clydelib.utilcore"
local signal = require "clydelib.signal"
local callback = require "clydelib.callback"
local aur = require "clydelib.aur"
local ui = require "clydelib.ui"
local needs_root = util.needs_root
local printf = util.printf
local lprintf = util.lprintf
local eprintf = util.eprintf
local basename = util.basename
local cleanup = util.cleanup
local tblinsert = util.tblinsert
local realpath = util.realpath
local strsplit = util.strsplit
local strtrim = util.strtrim
local g = utilcore.gettext
local bindtextdomain = utilcore.bindtextdomain
local textdomain = utilcore.textdomain
local geteuid = utilcore.geteuid
local C = colorize
local ROOTDIR = "/"
local PACMANCFG_PATH = "/etc/pacman.conf"
local CLYDECFG_PATH = "/etc/clyde.conf"
local DBPATH = "/var/lib/pacman/"
local CACHEDIR = "/var/cache/pacman/pkg/"
local LOGFILE = "/var/log/pacman.log"
local clydeconf = require "clydelib.config"
local PACKAGE = "clyde"
local LOCALEDIR = "/usr/share/locale"
local VERSION = '0.03.15'
local LUALPM_VERSION = '0.03'
local function usage(op, myname)
local str_opt = g("options")
local str_file = g("file(s)")
local str_pkg = g("package(s)")
local str_usg = g("usage")
local str_opr = g("operation")
if(op == "PM_OP_MAIN") then
printf("%s: %s <%s> [...]\n", str_usg, myname, str_opr)
printf(g("operations:\n"))
printf(" %s {-h --help}\n", myname)
printf(" %s {-V --version}\n", myname)
printf(" %s { --stats}\n", myname)
printf(" %s {-Q --query} [%s] [%s]\n", myname, str_opt, str_pkg)
printf(" %s {-R --remove} [%s] <%s>\n", myname, str_opt, str_pkg)
printf(" %s {-S --sync} [%s] [%s]\n", myname, str_opt, str_pkg)
printf(" %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file)
printf(" %s {-G --getpkgbuild} [%s] [%s]\n", myname, str_opt, str_pkg)
printf(g("\nuse '%s {-h --help}' with an operation for available options\n"), myname)
else
if (op == "PM_OP_REMOVE") then
printf("%s: %s {-R --remove} [%s] <%s>\n", str_usg, myname, str_opt, str_pkg)
printf("%s:\n", str_opt)
printf(g(" -c, --cascade remove packages and all packages that depend on them\n"))
printf(g(" -d, --nodeps skip dependency checks\n"))
printf(g(" -k, --dbonly only remove database entry, do not remove files\n"))
printf(g(" -n, --nosave remove configuration files as well\n"))
printf(g(" -s, --recursive remove dependencies also (that won't break packages)\
(-ss includes explicitly installed dependencies too)\n"))
printf(g(" -u, --unneeded remove unneeded packages (that won't break packages)\n"))
elseif(op == "PM_OP_UPGRADE") then
printf("%s: %s {-U --upgrade} [%s] <%s>\n", str_usg, myname, str_opt, str_file)
printf("%s:\n", str_opt)
printf(g(" --asdeps install packages as non-explicitly installed\n"))
printf(g(" --asexplicit install packages as explicitly installed\n"))
printf(g(" -d, --nodeps skip dependency checks\n"))
printf(g(" -f, --force force install, overwrite conflicting files\n"))
elseif(op == "PM_OP_QUERY") then
printf("%s: %s {-Q --query} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg)
printf("%s:\n", str_opt)
printf(g(" -c, --changelog view the changelog of a package\n"))
printf(g(" -d, --deps list packages installed as dependencies [filter]\n"))
printf(g(" -e, --explicit list packages explicitly installed [filter]\n"))
printf(g(" -g, --groups view all members of a package group\n"))
printf(g(" -i, --info view package information (-ii for backup files)\n"))
printf(g(" -k, --check check that the files owned by the package(s) are present\n"))
printf(g(" -l, --list list the contents of the queried package\n"))
printf(g(" -m, --foreign list installed packages not found in sync db(s) [filter]\n"))
printf(g(" -o, --owns <file> query the package that owns <file>\n"))
printf(g(" -p, --file <package> query a package file instead of the database\n"))
printf(g(" -s, --search <regex> search locally-installed packages for matching strings\n"))
printf(g(" -t, --unrequired list packages not required by any package [filter]\n"))
printf(g(" -u, --upgrades list outdated packages [filter]\n"))
printf(g(" -q, --quiet show less information for query and search\n"))
elseif(op == "PM_OP_SYNC") then
printf("%s: %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg)
printf("%s:\n", str_opt)
printf(g(" -a, --aur only search or install packages from AUR\n"))
printf(g(" --asdeps install packages as non-explicitly installed\n"))
printf(g(" --asexplicit install packages as explicitly installed\n"))
printf(g(" -c, --clean remove old packages from cache directory (-cc for all)\n"))
printf(g(" -d, --nodeps skip dependency checks\n"))
printf(g(" -f, --force force install, overwrite conflicting files\n"))
printf(g(" -g, --groups view all members of a package group\n"))
printf(g(" -i, --info view package information\n"))
printf(g(" -l, --list <repo> view a list of packages in a repo\n"))
printf(g(" -p, --print-uris print out URIs for given packages and their dependencies\n"))
printf(g(" -s, --search <regex> search remote repositories for matching strings\n"))
printf(g(" -u, --sysupgrade upgrade installed packages (-uu allows downgrade)\n"))
printf(g(" -w, --downloadonly download packages but do not install/upgrade anything\n"))
printf(g(" -y, --refresh download fresh package databases from the server\n"))
printf(g(" --user <user> user to run makepkg as when installing software from AUR\n"))
printf(g(" --needed don't reinstall up to date packages\n"))
printf(g(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n"))
printf(g(" --ignoregroup <grp>\
ignore a group upgrade (can be used more than once)\n"))
printf(g(" --repos only search or install packages from the configured repositories\n"))
printf(g(" -q, --quiet show less information for query and search\n"))
elseif(op == "PM_OP_GETPKG") then
printf("%s: %s {-G --getpkgbuild} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg)
printf("%s:\n", str_opt)
printf(g(" -d, --deps download files for dependencies from AUR as well\n"))
end
printf(g(" --config <path> set an alternate configuration file\n"))
printf(g(" --logfile <path> set an alternate log file\n"))
printf(g(" --noconfirm do not ask for any confirmation\n"))
printf(g(" --noprogressbar do not show a progress bar when downloading files\n"))
printf(g(" --noscriptlet do not execute the install scriptlet if one exists\n"))
printf(g(" -v, --verbose be verbose\n"))
printf(g(" --debug display debug messages\n"))
printf(g(" -r, --root <path> set an alternate installation root\n"))
printf(g(" -b, --dbpath <path> set an alternate database location\n"))
printf(g(" --cachedir <dir> set an alternate package cache location\n"))
printf(g(" --builddir <dir> set an alternate package build location\n"))
printf(g(" --editor <prg> edit the PKGBUILD with the configured editor\n"))
printf(g(" --color enable colors\n"))
printf(g(" --nocolor disable colors\n"))
end
end
--[[
local function version()
printf("\n")
printf(" .--. .---. Clyde v0.0.1 - lualpm v0.1.0\n")
printf(" '-._ \\ .-. .-|O O | ~~ Copyright (C) 2009 Robert Djubek\n")
printf(g(" .-' / '-' '-|~~~ | ~~~ This program may be freely redistributed under\n"))
printf(g(" '--' |.-.-.| ~~ the terms of the GNU General Public License.\n"))
printf("\n")
end
--]]
local function version()
printf("\n")
printf(C.yelb(" .--. ")..C.yel(" .---. ")..
"Clyde v%s - lualpm v%s\n", VERSION, LUALPM_VERSION)
printf(C.yelb(" '-._ \\")..C.bright(" .-. .-")..C.yel("|O O | ")..C.cya("~~ ").."Copyright (C) 2010 Robert Djubek\n")
printf(C.yelb(" .-' /")..C.bright(" '-' '-")..C.yel("|~~~ |")..C.red(" ~~~ ").."This program may be freely redistributed under\n")
printf(C.yelb(" '--' ")..C.yel(" |.-.-.|")..C.gre(" ~~ ").."the terms of the GNU General Public License.\n")
printf("\n")
end
local ranlocalize = false
local function localize()
if (not ranlocalize) then
local ret = os.setlocale("", "all")
local bind = bindtextdomain(PACKAGE, LOCALEDIR)
local text = textdomain(PACKAGE)
end
end
local function getopt_long(argv, sh_opts, long_opts, option_tbl)
local options = {}
local exit = false
local opttbl = option_tbl
if not next(options) then
local numargs = {
["no_argument"] = 0;
["required_argument"] = 1;
["optional_argument"] = 2;
}
for short, accept in sh_opts:gmatch("(%a)(:?:?)") do
options[short] = {["numarg"] = #accept, ["short"] = short}
end
for i, v in ipairs(long_opts) do
options[v[1]] = {["short"] = v[4], ["numarg"] = numargs[v[2]]}
end
end
local optindex = 0
local index = 2
return function()
while optindex < #argv do
optindex = optindex + 1
local argument = argv[optindex]
if argument == "--" then
optindex = optindex + 1
break
elseif argument == "-" then
break
elseif argument:sub(1,2) == "--" then
local pos = argument:find("=", 1, true)
if pos then
local option = argument:sub(3, pos -1)
if options[option] then
if options[option].numarg > 0 then
if argument:sub(pos + 1) then
return options[option].short, argument:sub(pos + 1)
else
print(basename(argv[0]) .. ": option '--" .. option .. "' requires an argument")
end
else
print(basename(argv[0]) .. ": option '--" .. option .. "' doesn\'t allow an argument")
end
else
print(basename(argv[0]) .. ": unrecognized option '--" .. option .. "'")
exit = true
break
end
else
local option = argument:sub(3)
if options[option] then
if options[option].numarg == 1 then
if optindex == #argv then
print(basename(argv[0]) .. ": option --'" .. option .. "' requires an argument")
elseif not argv[optindex + 1]:match("^%-") then
if options[option].numarg == 2 then
opttbl[#opttbl + 1] = argv[optindex + 1]
optindex = optindex + 1
return options[option].short, nil
else
optindex = optindex + 1
return options[option].short, argv[optindex]
end
else
print(basename(argv[0]) .. ": option --'" .. option .. "' requires an argument")
end
else
if argv[optindex + 1] and not argv[optindex + 1]:match("^%-") then
opttbl[#opttbl + 1] = argv[optindex + 1]
optindex = optindex + 1
return options[option].short, nil
else
return options[option].short, nil
end
end
else
print(basename(argv[0]) .. ": unrecognized option '--" .. option .. "'")
exit = true
break
end
end
elseif argument:sub(1, 1) == "-" then
for j = index, #argument do
local option = argument:sub(j, j)
if options[option] then
if options[option].numarg > 0 then
if optindex == #argv then
print(basename(argv[0]) .. ": option requires an argument -- '" .. option .. "'")
elseif not argv[optindex + 1]:match("^%-") then
if options[option].numarg == 2 then
opttbl[#opttbl + 1] = argv[optindex + 1]
optindex = optindex + 1
return options[option].short, nil
else
optindex = optindex + 1
return options[option].short, argv[optindex]
end
else
print(basename(argv[0]) .. ": option requires an argument -- '" .. option .. "'")
end
else
optindex = optindex - 1
index = index + 1
return options[option].short, nil
end
else
print(basename(argv[0]) .. ": invalid option -- '" .. option .. "'")
exit = true
break
end
end
index = 2
else
if optindex <= #argv then
local option = argv[optindex]
opttbl[#opttbl +1] = argv[optindex]
end
end
end
if exit == true then cleanup(1) return nil end
end
end
local function set_builddir ( builddir )
lprintf("LOG_DEBUG", "config: builddir: %s\n", str)
config.builddir = builddir
end
local function parseargs()
local longopts = {
--[[
--clyde specific options
--]]
{"aur", "no_argument", 0, 'a'},
{"nocolor", "no_argument", 0, 'OP_NOCOLOR'},
{"color", "no_argument", 0, 'OP_COLOR'},
{"stats", "no_argument", 0, 'OP_STATS'},
{"editor", "required_argument",0, 'OP_EDITOR'},
{"repos", "no_argument", 0, 'OP_REPOS'},
{"getpkgbuild", "no_argument", 0, 'G'},
{"user", "required_argument",0, 'OP_BUILD'},
{"builddir", "required_argument",0, 'OP_BUILDDIR'},
--[[
--pacman feature functions
--]]
{"query", "no_argument", 0, 'Q'},
{"remove", "no_argument", 0, 'R'},
{"sync", "no_argument", 0, 'S'},
{"deptest", "no_argument", 0, 'T'},
{"upgrade", "no_argument", 0, 'U'},
{"version", "no_argument", 0, 'V'},
{"dbpath", "required_argument", 0, 'b'},
{"cascade", "no_argument", 0, 'c'},
{"changelog", "no_argument", 0, 'c'},
{"clean", "no_argument", 0, 'c'},
{"nodeps", "no_argument", 0, 'd'},
{"deps", "no_argument", 0, 'd'},
{"explicit", "no_argument", 0, 'e'},
{"force", "no_argument", 0, 'f'},
{"groups", "no_argument", 0, 'g'},
{"help", "no_argument", 0, 'h'},
{"info", "no_argument", 0, 'i'},
{"dbonly", "no_argument", 0, 'k'},
{"check", "no_argument", 0, 'k'},
{"list", "no_argument", 0, 'l'},
{"foreign", "no_argument", 0, 'm'},
{"nosave", "no_argument", 0, 'n'},
{"owns", "no_argument", 0, 'o'},
{"file", "no_argument", 0, 'p'},
{"print-uris", "no_argument", 0, 'p'},
{"quiet", "no_argument", 0, 'q'},
{"root", "required_argument", 0, 'r'},
{"recursive", "no_argument", 0, 's'},
{"search", "no_argument", 0, 's'},
{"unrequired", "no_argument", 0, 't'},
{"upgrades", "no_argument", 0, 'u'},
{"sysupgrade", "no_argument", 0, 'u'},
{"unneeded", "no_argument", 0, 'u'},
{"verbose", "no_argument", 0, 'v'},
{"downloadonly", "no_argument", 0, 'w'},
{"refresh", "no_argument", 0, 'y'},
{"noconfirm", "no_argument", 0, 'OP_NOCONFIRM'},
{"config", "required_argument", 0, 'OP_CONFIG'},
{"ignore", "required_argument", 0, 'OP_IGNORE'},
{"debug", "optional_argument", 0, 'OP_DEBUG'},
{"noprogressbar", "no_argument", 0, 'OP_NOPROGRESSBAR'},
{"noscriptlet", "no_argument", 0, 'OP_NOSCRIPTLET'},
-- {"ask", "required_argument", 0, 'OP_ASK'},
{"cachedir", "required_argument", 0, 'OP_CACHEDIR'},
{"asdeps", "no_argument", 0, 'OP_ASDEPS'},
{"logfile", "required_argument", 0, 'OP_LOGFILE'},
{"ignoregroup", "required_argument", 0, 'OP_IGNOREGROUP'},
{"needed", "no_argument", 0, 'OP_NEEDED'},
{"asexplicit", "no_argument", 0, 'OP_ASEXPLICIT'},
-- {"arch", "required_argument", 0, 'OP_ARCH'},
}
local settrans = function(val)
return function()
if config.op ~= "PM_OP_MAIN" then
config.op = nil
else
config.op = val
end
end
end
local lookuptbl = {
--[[
--clyde specific options
--]]
['a'] = function()
config.op_s_search_aur_only = true
config.op_s_upgrade_aur = true
end;
['OP_NOCOLOR'] = function()
config.op_use_color = false
colorize.disable()
end;
['OP_COLOR'] = function()
config.op_use_color = true
colorize.enable()
end;
['OP_STATS'] = function()
config.stats = true
end;
['OP_EDITOR'] = function(opt)
config.editor = opt
end;
['OP_REPOS'] = function()
config.op_s_search_repos_only = true
end;
['G'] = settrans('PM_OP_GETPKG');
['OP_BUILD'] = function(opt)
config.op_s_build_user = opt
end;
['OP_BUILDDIR'] = function(opt) set_builddir( opt ) end;
--[[
--pacman feature functions
--]]
['Q'] = settrans('PM_OP_QUERY');
['R'] = settrans('PM_OP_REMOVE');
['S'] = settrans('PM_OP_SYNC');
['T'] = settrans('PM_OP_DEPTEST');
['U'] = settrans('PM_OP_UPGRADE');
['V'] = function() config.version = true end;
['b'] = function(opt) config.dbpath = opt end;
['c'] = function()
config.op_s_clean = config.op_s_clean + 1
config.flags["cascade"] = true
config.op_q_changelog = true
end;
['d'] = function()
-- -d sets nodepver, -dd sets nodeps
-- ignore more than two, it would just confuse us...
if config.flags.nodeps then return end
if not config.flags.nodepver then
-- first time we see -d
config.op_q_deps = true
config.op_g_get_deps = true
config.flags.nodepver = true
else
-- second time
config.flags.nodepver = false
config.flags.nodeps = true
end
end;
['e'] = function() config.op_q_explicit = true end;
['f'] = function() config.flags["force"] = true end;
['g'] = function() config.group = config.group + 1 end;
['h'] = function() config.help = true end;
['i'] = function()
config.op_q_info = config.op_q_info + 1
config.op_s_info = true
end;
['k'] = function()
config.flags["dbonly"] = true
config.op_q_check = true
end;
['l'] = function() config.op_q_list = true end;
['m'] = function() config.op_q_foreign = true end;
['n'] = function() config.flags["nosave"] = true end;
['o'] = function() config.op_q_owns = true end;
['p'] = function()
config.op_q_isfile = true
config.op_s_printuris = true
config.flags["noconflicts"] = true
config.flags["nolock"] = true
end;
['q'] = function() config.quiet = true end;
['r'] = function(opt) config.rootdir = opt end;
['s'] = function()
config.op_s_search = true
config.op_q_search = true
if config.flags["recurse"] then
config.flags["recurseall"] = true
else
config.flags["recurse"] = true
end
end;
['t'] = function() config.op_q_unrequired = true end;
['u'] = function()
config.op_s_upgrade = config.op_s_upgrade + 1
config.op_q_upgrade = true
config.flags["unneeded"] = true
end;
['v'] = function() config.verbose = config.verbose + 1 end;
['w'] = function()
config.op_s_downloadonly = true
config.flags["downloadonly"] = true
config.flags["noconflicts"] = true
end;
['y'] = function() config.op_s_sync = config.op_s_sync + 1 end;
['OP_NOCONFIRM'] = function() config.noconfirm = true end;
['OP_CONFIG'] = function(opt) config.configfile = opt end;
['OP_IGNORE'] = function(opt)
if (opt) then
local list = strsplit(opt, ",")
for i, ignore in ipairs(list) do
alpm.option_add_ignorepkg(ignore)
end
end
end;
['OP_DEBUG'] = function(opt)
if (opt) then
if opt == '2' then
tblinsert(config.logmask, "LOG_FUNCTION")
tblinsert(config.logmask, "LOG_DEBUG")
elseif opt == '1' then
tblinsert(config.logmask, "LOG_DEBUG")
else
--TODO: logging
lprintf("LOG_ERROR", g("'%s' is not a valid debug level\n"), opt)
return 1
end
else
tblinsert(config.logmask, "LOG_DEBUG")
end
config.noprogressbar = true
end;
['OP_NOPROGRESSBAR'] = function() config.noprogressbar = true end;
['OP_NOSCRIPTLET'] = function()
config.flags["noscriptlet"] = true
end;
-- ['OP_ASK'] = function() end;
['OP_CACHEDIR'] = function(opt)
local result = alpm.option_add_cachedir(opt)
if (result ~= 0) then
lprintf("LOG_ERROR", g("problem adding cachedir '%s' (%s)\n"), opt, alpm.strerrorlast())
return 1
end
end;
['OP_ASDEPS'] = function()
config.flags["alldeps"] = true
end;
['OP_LOGFILE'] = function(opt) config.logfile = opt end;
['OP_IGNOREGROUP'] = function(opt)
if (opt) then
local list = strsplit(opt, ",")
for i, ignore in ipairs(list) do
alpm.option_add_ignoregrp(ignore)
end
end
end;
['OP_NEEDED'] = function() config.flags["needed"] = true end;
['OP_ASEXPLICIT'] = function() config.flags["allexplicit"] = true end;
-- ['OP_ARCH'] = function() end;
}
local shortopts = "RUQSTr:b:vkhscVfmnoldepqituwyg"
local clydeshortopts = "Ga"
shortopts = shortopts..clydeshortopts
local opttable = {}
for elem, option in getopt_long(arg, shortopts, longopts, opttable) do
if lookuptbl[elem] then
lookuptbl[elem](option)
-- TODO: check return code
else
print("not implemented yet, fix this")
end
end
if (config.op == nil) then
lprintf("LOG_ERROR", g("only one operation may be used at a time\n"))
return 1
end
if (config.stats) then
return 0
end
if (config.help) then
usage(config.op, basename(arg[0]))
return 2
end
if (config.version) then
version()
return 2
end
pm_targets = opttable
return 0
end
local ransetlibpaths = false
local function setlibpaths()
if (ransetlibpaths) then return end
ransetlibpaths = true
local result
lprintf("LOG_DEBUG", "setlibpaths() called\n")
if (config.rootdir) then
result = alpm.option_set_root(config.rootdir)
if (result ~= 0) then
lprintf("LOG_ERROR", g("problem setting rootdir '%s' (%s)\n"), config.rootdir, alpm.strerrorlast())
cleanup(ret)
end
if (not config.dbpath) then
config.dbpath = alpm.option_get_root() .. DBPATH:match("/(.*)")
end
if (not config.logfile) then
config.logfile = alpm.option_get_root() .. LOGFILE:match("/(.*)")
end
end
if (config.dbpath) then
result = alpm.option_set_dbpath(config.dbpath)
if (result ~= 0) then
eprintf("LOG_ERROR", g("problem setting dbpath '%s' (%s)\n"), config.dbpath, alpm.strerrorlast())
cleanup(result)
end
end
if (config.logfile) then
result = alpm.option_set_logfile(config.logfile)
if (result ~= 0) then
eprintf("LOG_ERROR", g("problem setting logfile '%s' (%s)\n"), config.logfile, alpm.strerrorlast)
cleanup(result)
end
end
if (not next(alpm.option_get_cachedirs())) then
alpm.option_add_cachedir(CACHEDIR)
end
end
local function config_init(uid)
config = clydeconf
tblinsert(config.logmask, "LOG_ERROR")
tblinsert(config.logmask, "LOG_WARNING")
local testconf = io.open(CLYDECFG_PATH)
if (testconf) then
config.configfile = CLYDECFG_PATH
testconf:close()
else
config.configfile = PACMANCFG_PATH
end
if (uid == 0 and not testconf) then
local response = util.yesno("You do not yet have a clyde.conf, would you like to create one?")
if (response) then
local fdpacman = io.open(PACMANCFG_PATH, "r")
local paclines = {}
while true do
local line = fdpacman:read("*l")
if line == nil then break end
table.insert(paclines, line .. "\n")
end
fdpacman:close()
-- move the header from pacman.conf to the top of clyde.conf
local header = ""
while paclines[1]:match("^#") do
header = header .. table.remove( paclines, 1 )
end
if paclines[1]:match("^%s*$") then
-- blank line too
table.remove( paclines, 1 )
end
header = header:gsub(PACMANCFG_PATH:gsub("%.", "%%."),
CLYDECFG_PATH:gsub ("%.", "%%."))
local confirm = false
local editor
printf("Please enter your default text editor: ")
while (not confirm) do
editor = io.read()
confirm = util.yesno("You entered '%s' as your default "
.. "editor, is this correct? ", editor)
if not confirm then printf("Editor: ") end
end
local clydeopts = [[
#
# CLYDE OPTIONS
#
[clydeoptions]
# Uncomment the following line to disable colors.
#NoColor
# Uncomment to only search the AUR explicitly. (You would have to use --aur)
#ReposOnly
# Which program to use for editing PKGBUILDs.
Editor = %s
# You must set this to a normal user to safely build packages from the AUR
# when running without sudo.
BuildUser = %s
# If no BuildDir is set, then a directory is created for your BuildUser
# Otherwise the exact directory name you provide is used.
#BuildDir = /tmp/clyde-<BuildUser> (default when unset)
]]
-- Not sure what to set for default BuildUser
local username = os.getenv("SUDO_USER") or "nobody"
clydeopts = string.format(clydeopts, editor, username)
local fdclyde = io.open(CLYDECFG_PATH, "w")
fdclyde:write(header, "\n", clydeopts, table.concat(paclines))
fdclyde:close()
printf([[Congratulations! Your new config file is ready to use.
Additional defaults have been set. Please double-check %s.
]], CLYDECFG_PATH)
config.configfile = CLYDECFG_PATH
end
end
end
local function config_free(conf)
if (type(conf) ~= "table") then return end
for k, v in pairs(conf) do
k = nil
end
conf = nil
end
local function option_add_holdpkg(name)
config.holdpkg[ name ] = true
end
local function option_add_syncfirst(name)
tblinsert(config.syncfirst, name)
end
local function setrepeatingoption(str, option, optionfunc)
local options = strsplit(str, ' ')
for i, opt in ipairs(options) do
optionfunc(opt)
lprintf("LOG_DEBUG", "config: %s: %s\n", option, opt)
end
end
local function _parseconfig(file, givensection, givendb)
local ret = 0
local cont = true
--TODO: make sure return configcleanup() is right
local function configcleanup()
if (fp) then
fp:close()
end
if (section) then
section = nil
end
setlibpaths()
lprintf("LOG_DEBUG", "config: finished parsing %s\n", file)
cont = false
return ret
--if (cont == false) then
-- return 1
--else
-- return 0
--end
end
local optionlookuptbl = {
--[[
--clyde specific options
--]]
['NoColor'] = function()
if (config.op_use_color ~= true) then
config.op_use_color = false
colorize.disable()
lprintf("LOG_DEBUG", "config: nocolor\n")
end
end;
['Editor'] = function(str)
if (not config.editor) then
config.editor = str
lprintf("LOG_DEBUG", "config: editor: %s\n", str)
end
end;
['ReposOnly'] = function()
if (not config.op_s_search_aur_only) then
config.op_s_search_repos_only = true
lprintf("LOG_DEBUG", "config: reposonly\n")
end
end;
['BuildUser'] = function (user)
if config.build_user then
lprintf("LOG_WARNING", "overwriting previous BuildUser\n")
end
local success, result = pcall(utilcore.getpwnam, user)
if not result then
result = "unknown user "..user
success = false
end
if not success then
lprintf("LOG_ERROR", "could not set BuildUser: %s\n", result)
ret = 1
return configcleanup()
end
config.build_user = { name = result.name;
uid = result.uid;
gid = result.gid }
lprintf("LOG_DEBUG", "config: builduser = "..user.."\n")
end;
['BuildDir'] = function(str) set_builddir(str) end;
--[[
--pacman feature functions
--]]
['UseSyslog'] = function() alpm.option_set_usesyslog(true)
lprintf("LOG_DEBUG", "config: usesyslog\n") end;
['ILoveCandy'] = function() config.chomp = true
lprintf("LOG_DEBUG", "config: chomp\n") end;
['ShowSize'] = function() config.showsize = true
lprintf("LOG_DEBUG", "config: showsize\n") end;
['UseDelta'] = function() alpm.option_set_usedelta(true)
lprintf("LOG_DEBUG", "config: usedelta\n") end;
['TotalDownload'] = function() config.totaldownload = true
lprintf("LOG_DEBUG", "config: totaldownload\n") end;
['CheckSpace'] = function ()
alpm.option_set_checkspace(true)
lprintf("LOG_DEBUG", "config: checkspace\n")
end;
['NoUpgrade'] = function(str)
setrepeatingoption(str, "NoUpgrade", alpm.option_add_noupgrade) end;
['NoExtract'] = function(str)
setrepeatingoption(str, "NoExtract", alpm.option_add_noextract) end;
['IgnorePkg'] = function(str)
setrepeatingoption(str, "IgnorePkg", alpm.option_add_ignorepkg) end;
['IgnoreGroup'] = function(str)
setrepeatingoption(str, "IgnoreGroup", alpm.option_add_ignoregrp) end;
['HoldPkg'] = function(str)
setrepeatingoption(str, "HoldPkg", option_add_holdpkg) end;
['SyncFirst'] = function(str)
setrepeatingoption(str, "SyncFirst", option_add_syncfirst) end;
['Architecture'] = function(str)
if (not alpm.option_get_arch()) then
if (str == "auto") then
str = utilcore.arch();
end
alpm.option_set_arch(str)
end
end;
['DBPath'] = function(str)
if (not config.dbpath) then
config.dbpath = str
lprintf("LOG_DEBUG", "config: dbpath: %s\n", str)
end
end;
['CacheDir'] = function(str)
if (not alpm.option_add_cachedir(str)) then
lprintf("LOG_ERROR", g("problem adding cachedir '%s' (%s)\n"),
str, alpm.strerrorlast())
ret = 1
return configcleanup()
end
lprintf("LOG_DEBUG", "config: cachedir: %s\n", str)
end;
['RootDir'] = function(str)
if (not config.rootdir) then
config.rootdir = str
lprintf("LOG_DEBUG", "config: rootdir: %s\n", str)
end
end;
['LogFile'] = function(str)
if (not config.logfile) then
config.logfile = str
lprintf("LOG_DEBUG", "config: logfile: %s\n", str)
end
end;
['XferCommand'] = function(str)
alpm.option_set_fetchcb( callback.create_xfercmd_cb( str ))
lprintf("LOG_DEBUG", "config: xfercommand: %s\n", str)
end;
['CleanMethod'] = function(str)
if (str == "KeepInstalled") then
config.cleanmethod = "CLEAN_KEEPINST"
elseif (str == "KeepCurrent") then
config.cleanmethod = "CLEAN_KEEPCUR"
else
lprintf("LOG_ERROR", g("invalid value for 'CleanMethod' : '%s'\n"), str)
ret = 1
return configcleanup()
end
lprintf("LOG_DEBUG", "config: cleanmethod: %s\n", str)
end;
}
local section, db
local linenum = 0
lprintf("LOG_DEBUG", "config: attempting to read file %s\n", file)
local fp, err = io.open(file)
if err then
lprintf("LOG_ERROR", g("config file %s could not be read.\n"), file)
return 1
end
if (givensection) then
section = givensection
end
if (givendb) then
db = givendb
end
for line in fp:lines() do
if (not cont) then return ret end
repeat
linenum = linenum + 1
line = strtrim(line)
if (#line == 0) or (line:match("^#")) then
break
end
local pos = line:find("#")
if pos then
line = line:sub(1, pos - 1)
line = strtrim(line)
end
if (line:sub(1,1) == '[') and (line:sub(-1) == ']') then
section = line:match("^%[(.+)%]$")
lprintf("LOG_DEBUG", "config: new section '%s'\n", section)
if #section == 0 then
lprintf("LOG_ERROR", g("config file %s, line %d: bad section name.\n"),
file, linenum)
ret = 1
return configcleanup()
end
if (section ~= "options" and section ~= "clydeoptions") then
db = alpm.db_register_sync(section)
if (db == nil) then
lprintf("LOG_ERROR", g("could not register '%s' database (%s)\n"),
section, alpm.strerrorlast())
ret = 1
return configcleanup()
end
end
else
local key, str = line:match("(%S+)%s*=%s*(.*)")
if (not key) then key = line end
if (not section) then
lprintf("LOG_ERROR", g("config file %s, line %d: All directives must belong to a section.\n"),
file, linenum)
ret = 1
return configcleanup()
end
if (str == nil) and (section == "options" or section == "clydeoptions") then
if (optionlookuptbl[key]) then
optionlookuptbl[key]()
else
lprintf("LOG_ERROR", g("config file %s, line %d: directive '%s' not recognized.\n"),
file, linenum, key)
ret = 1
return configcleanup()
end
else
if (key == "Include") then
lprintf("LOG_DEBUG", "config: including %s\n", str)
_parseconfig(str, section, db)
elseif (section == "options" or section == "clydeoptions") then
if (optionlookuptbl[key]) then
optionlookuptbl[key](str)
else
lprintf("LOG_ERROR", g("config file %s, line %d: directive '%s' not recognized.\n"),
file, linenum, key)
ret = 1
return configcleanup()
end
elseif (key == "Server") then
local server = str:gsub("%$repo", section)
if (server:match("%$arch")) then
local arch = alpm.option_get_arch()
if ( not arch ) then
lprintf("LOG_ERROR",
g("The mirror '%s' contains the $arch" ..
" variable, but no Architecture is defined.\n"), str)
ret = 1
return configcleanup()
end
server = server:gsub("%$arch", arch)
end
if (db:db_setserver(server) ~= 0) then
lprintf("LOG_ERROR", g("could not add server URL to database '%s': %s (%s)\n"),
db:db_get_name(), server, alpm.strerrorlast())
ret = 1
return configcleanup()
end
server = nil
else
lprintf("LOG_ERROR", g("config file %s, line %d: directive '%s' not recognized.\n"),
file, linenum, key)
ret = 1
return configcleanup()
end
end
end
until 1
end
return configcleanup()
end
local function parseconfig(file)
return _parseconfig(file, nil, nil)
end
-- Offer to install packages in the package_names list
-- Returns the names of packages they want to install.
local function offer_install_pkgs ( package_names )
if not next( package_names ) then return {} end
local bars = C.yelb("==>")
printf("\n%s %s\n%s %s\n",
bars,
C.bright("Enter #'s (separated by blanks) of packages "
.. "to be installed"),
bars, C.bright(string.rep( "-", 60 )), bars )
local max = #package_names
local chosen = ui.prompt_for_numbers( bars, max )
if not chosen then
print( "Aborting." )
return {}
end
for i, n in ipairs( chosen ) do chosen[i] = package_names[n] end
return chosen
end
function main()
local ret = 0
utilcore.setprocname( "clyde" )
utilcore.umask( "0133" ) -- should this be more restrictive?
signal.signal("SIGINT", function()
printf("\nInterrupt signal received\n\n")
alpm.trans_interrupt() -- try to be nice
util.trans_release()
cleanup(2)
end)
signal.signal("SIGTERM", function()
cleanup(15)
end)
signal.signal("SIGPIPE", nil)
local myuid = geteuid()
localize()
alpm.initialize()
config_init(myuid)
if (utilcore.isatty(1) == 0 and not config.op_use_color) then
colorize.disable()
end
alpm.option_set_logcb(callback.cb_log)
alpm.option_set_dlcb(callback.cb_dl_progress)
alpm.option_set_root(ROOTDIR)
alpm.option_set_dbpath(DBPATH)
alpm.option_set_logfile(LOGFILE)
ret = parseargs()
if (ret ~= 0) then
cleanup(ret)
end
ret = parseconfig(config.configfile)
if (ret ~= 0) then
cleanup(ret)
end
if (config.stats) then
packages.packagestats()
cleanup(0)
end
if (config.totaldownload) then
alpm.option_set_totaldlcb(callback.cb_dl_total)
end
if (myuid > 0 and needs_root()) then
lprintf("LOG_ERROR", g("you cannot perform this operation unless you are root.\n"))
cleanup(1)
end
if (config.verbose > 0) then
printf("Root : %s\n", alpm.option_get_root())
printf("Conf File : %s\n", config.configfile)
printf("DB Path : %s\n", alpm.option_get_dbpath())
printf("Cache Dirs: ")
local cachedirs = alpm.option_get_cachedirs()
for i, v in ipairs(cachedirs) do
printf("%s ", v)
end
print()
printf("Lock File : %s\n", alpm.option_get_lockfile())
printf("Log File : %s\n", alpm.option_get_logfile())
printf("Targets : ")
local targets = pm_targets or {}
for i, v in ipairs(targets) do
printf("%s ", v)
end
print()
end
local lookuptbl = {
['PM_OP_QUERY'] = function() return query.main(pm_targets) end;
['PM_OP_UPGRADE'] = function() return upgrade.main(pm_targets) end;
['PM_OP_REMOVE'] = function() return remove.main(pm_targets) end;
['PM_OP_SYNC'] = function() return sync.main(pm_targets) end;
['PM_OP_DEPTEST'] = function() return deptest.main(pm_targets) end;
['PM_OP_GETPKG'] = function() return sync.getpkgbuild(pm_targets) end;
}
local ran = false
if (config.op ~= "PM_OP_MAIN") then
ret = lookuptbl[config.op]()
ran = true
elseif next(pm_targets) then
local found_names = sync.sync_search( pm_targets, true )
if not next( found_names ) then return 1 end
local install = offer_install_pkgs( found_names )
if not next( install ) then return 1 end
if (myuid > 0) then
-- See whether sudo (preferable) or su exist
local sucmds = { { file = "/usr/bin/sudo",
prefix = "%s sh -c" },
{ file = "/bin/su",
prefix = "%s -c" }, }
local prefix
for i, sucmd in ipairs( sucmds ) do
-- Cannot use io.open because sudo doesn't give
-- read access to anyone.
if lfs.attributes( sucmd.file ) then
prefix = string.format( sucmd.prefix,
sucmd.file )
break
end
end
if not prefix then
eprintf( "LOG_ERROR",
"neither sudo nor su are installed, cannot "
.. "automatically install search results" )
os.exit( 1 )
end
local cmd = string.format( "%s '%s -S %s'",
prefix, arg[0],
table.concat( install, " " ))
return os.execute(cmd)
else
ret = sync.main(install)
return ret
end
else
eprintf("LOG_ERROR", g("no operation specified (use -h for help)\n"))
os.exit(1)
end
if (next(pm_targets) and ran and not ret and ret ~= nil) then
print(ret)
if alpm.trans_release() == -1 then
eprintf("LOG_ERROR", "%s\n", alpm.strerrorlast())
end
end
if (type(config.configfile) == "userdata") then
config.configfile:close()
end
return ret
end
os.exit(main())
-- Local Variables:
-- mode: lua
-- lua-indent-level: 4
-- End:
Jump to Line
Something went wrong with that request. Please try again.