aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.nim45
-rw-r--r--src/main.nim13
-rw-r--r--src/pacman.nim57
3 files changed, 71 insertions, 44 deletions
diff --git a/src/config.nim b/src/config.nim
index 2aa9974..be27291 100644
--- a/src/config.nim
+++ b/src/config.nim
@@ -20,14 +20,16 @@ type
progressBar*: bool
verbosePkgList*: bool
pgpKeyserver*: Option[string]
+ defaultRoot*: bool
ignorePkgs*: HashSet[string]
ignoreGroups*: HashSet[string]
PacmanConfig* = object of CommonConfig
- rootOption*: Option[string]
- dbOption*: Option[string]
- cacheOption*: Option[string]
- gpgOption*: Option[string]
+ sysrootOption*: Option[string]
+ rootRelOption*: Option[string]
+ dbRelOption*: Option[string]
+ cacheRelOption*: Option[string]
+ gpgRelOption*: Option[string]
colorMode*: ColorMode
Config* = object of CommonConfig
@@ -95,36 +97,42 @@ proc readConfigFile*(configFile: string):
proc ignored*(config: Config, name: string, groups: openArray[string]): bool =
name in config.ignorePkgs or (config.ignoreGroups * groups.toSet).len > 0
-proc isRootDefault*(config: Config): bool =
- config.root == "/"
-
proc get*(colorMode: ColorMode): bool =
case colorMode:
of ColorMode.colorNever: false
of ColorMode.colorAlways: true
of ColorMode.colorAuto: isatty(1) == 1
-proc root*(config: PacmanConfig): string =
- config.rootOption.get("/")
+proc pacmanRootRel*(config: PacmanConfig): string =
+ config.rootRelOption.get("/")
-proc db*(config: PacmanConfig): string =
- if config.dbOption.isSome:
- config.dbOption.unsafeGet
+proc pacmanDbRel*(config: PacmanConfig): string =
+ if config.dbRelOption.isSome:
+ config.dbRelOption.unsafeGet
else:
- let root = config.root
+ let root = config.pacmanRootRel
let workRoot = if root == "/": "" else: root
workRoot & localStateDir & "/lib/pacman/"
-proc cache*(config: PacmanConfig): string =
- config.cacheOption.get(localStateDir & "/cache/pacman/pkg")
+proc pacmanCacheRel*(config: PacmanConfig): string =
+ config.cacheRelOption.get(localStateDir & "/cache/pacman/pkg")
+
+proc simplifyConfigPath(path: string): string =
+ if path.find("//") >= 0:
+ simplifyConfigPath(path.replace("//", "/"))
+ else:
+ path
+
+proc extendRel*(pathRel: string, sysroot: Option[string]): string =
+ sysroot.map(s => (s & "/" & pathRel).simplifyConfigPath).get(pathRel)
proc obtainConfig*(config: PacmanConfig): Config =
let (configTable, _) = readConfigFile(sysConfDir & "/pakku.conf")
let options = configTable.opt("options").map(t => t[]).get(initTable[string, string]())
- let root = config.root
- let db = config.db
- let cache = config.cache
+ let root = config.pacmanRootRel.extendRel(config.sysrootOption)
+ let db = config.pacmanDbRel.extendRel(config.sysrootOption)
+ let cache = config.pacmanCacheRel.extendRel(config.sysrootOption)
let color = config.colorMode.get
proc handleDirPattern(dirPattern: string, user: User): string =
@@ -160,6 +168,7 @@ proc obtainConfig*(config: PacmanConfig): Config =
tmpRootInitial: tmpRootInitial, tmpRootCurrent: tmpRootCurrent, color: color,
dbs: config.dbs, arch: config.arch, debug: config.debug, progressBar: config.progressBar,
verbosePkgList: config.verbosePkgList, pgpKeyserver: config.pgpKeyserver,
+ defaultRoot: config.defaultRoot and config.sysrootOption.isNone,
ignorePkgs: config.ignorePkgs, ignoreGroups: config.ignoreGroups,
aurComments: aurComments, checkIgnored: checkIgnored, printAurNotFound: printAurNotFound,
sudoExec: sudoExec, viewNoDefault: viewNoDefault, preserveBuilt: preserveBuilt,
diff --git a/src/main.nim b/src/main.nim
index 7171716..54fbb08 100644
--- a/src/main.nim
+++ b/src/main.nim
@@ -9,6 +9,10 @@ import
"feature/syncsource",
"feature/localquery"
+proc execSudo*(args: seq[Argument]): int =
+ execResult(sudoPrefix & getAppFilename() &
+ lc[x | (y <- args, x <- y.collectArg), string])
+
proc passValidation(args: seq[Argument], config: Config,
nonRootArgs: openArray[OptionPair], rootArgs: openArray[OptionPair],
opts: varargs[seq[CommandOption]]): int =
@@ -90,11 +94,9 @@ proc handleSync(args: seq[Argument], config: Config): int =
let printMode = args.check(%%%"print") or args.check(%%%"print-format")
if currentUser.uid != 0 and config.sudoExec and not printMode:
- let collectedArgs = sudoPrefix & getAppFilename() &
- lc[x | (y <- args, x <- y.collectArg), string]
- execResult(collectedArgs)
+ execSudo(args)
else:
- let isNonDefaultRoot = not config.isRootDefault
+ let isNonDefaultRoot = not config.defaultRoot
let isRootNoDrop = currentUser.uid == 0 and not canDropPrivileges()
let build = args.check(%%%"build")
@@ -225,6 +227,9 @@ let init = withErrorHandler(none(bool),
parsedArgs.check((some("V"), "version")):
let code = handleVersion()
raise haltError(code)
+ elif parsedArgs.check(%%%"sysroot") and currentUser.uid != 0:
+ let code = execSudo(parsedArgs)
+ raise haltError(code)
else:
let pacmanConfig = obtainPacmanConfig(parsedArgs)
let config = obtainConfig(pacmanConfig)
diff --git a/src/pacman.nim b/src/pacman.nim
index af8902b..067906d 100644
--- a/src/pacman.nim
+++ b/src/pacman.nim
@@ -84,6 +84,7 @@ const
^o("logfile"),
o("noconfirm"),
o("confirm"),
+ ^o("sysroot"),
^o("ask")
]
@@ -278,9 +279,9 @@ proc pacmanRun*(root: bool, color: bool, args: varargs[Argument]): int =
let argsSeq = @args
forkWait(() => pacmanExec(root, color, argsSeq))
-proc pacmanValidateAndThrow(args: varargs[Argument]): void =
+proc pacmanValidateAndThrow(args: varargs[tuple[arg: Argument, pass: bool]]): void =
let argsSeq = @args
- let collectedArgs = lc[x | (y <- argsSeq, x <- y.collectArg), string]
+ let collectedArgs = lc[x | (y <- argsSeq, y.pass, x <- y.arg.collectArg), string]
let code = forkWait(() => pacmanExecInternal(false, "-T" & collectedArgs))
if code != 0:
raise haltError(code)
@@ -291,10 +292,10 @@ proc getMachineName: Option[string] =
if length > 0: some(utsname.machine.toString(some(length))) else: none(string)
proc createConfigFromTable(table: Table[string, string], dbs: seq[string]): PacmanConfig =
- let root = table.opt("RootDir")
- let db = table.opt("DBPath")
- let cache = table.opt("CacheDir")
- let gpg = table.opt("GPGDir")
+ let rootRel = table.opt("RootDir")
+ let dbRel = table.opt("DBPath")
+ let cacheRel = table.opt("CacheDir")
+ let gpgRel = table.opt("GPGDir")
let color = if table.hasKey("Color"): ColorMode.colorAuto else: ColorMode.colorNever
let verbosePkgList = table.hasKey("VerbosePkgLists")
let arch = table.opt("Architecture").get("auto")
@@ -306,33 +307,38 @@ proc createConfigFromTable(table: Table[string, string], dbs: seq[string]): Pacm
raise commandError(tr"can not get the architecture",
colorNeeded = some(color.get))
- PacmanConfig(rootOption: root, dbOption: db, cacheOption: cache, gpgOption: gpg,
+ PacmanConfig(sysrootOption: none(string), rootRelOption: rootRel,
+ dbRelOption: dbRel, cacheRelOption: cacheRel, gpgRelOption: gpgRel,
dbs: dbs, arch: archFinal, colorMode: color, debug: false, progressBar: true,
- verbosePkgList: verbosePkgList, pgpKeyserver: none(string),
+ verbosePkgList: verbosePkgList, pgpKeyserver: none(string), defaultRoot: true,
ignorePkgs: ignorePkgs, ignoreGroups: ignoreGroups)
proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig =
proc getAll(pair: OptionPair): seq[string] =
args.filter(arg => arg.matchOption(pair)).map(arg => arg.value.get)
- let configFile = getAll(%%%"config").optLast.get(sysConfDir & "/pacman.conf")
- let (configTable, wasError) = readConfigFile(configFile)
+ let sysroot = args.filter(a => a.matchOption(%%%"sysroot")).optFirst.map(a => a.value).flatten
+
+ let configFileRel = getAll(%%%"config").optLast.get(sysConfDir & "/pacman.conf")
+ let (configTable, wasError) = readConfigFile(configFileRel.extendRel(sysroot))
let options = configTable.opt("options").map(t => t[]).get(initTable[string, string]())
let dbs = toSeq(configTable.keys).filter(k => k != "options")
let defaultConfig = createConfigFromTable(options, dbs)
if wasError:
- pacmanValidateAndThrow(("config", some(configFile), ArgumentType.long))
+ pacmanValidateAndThrow((("sysroot", sysroot, ArgumentType.long), sysroot.isSome),
+ (("config", some(configFileRel), ArgumentType.long), true))
+ raise haltError(1)
proc getColor(color: string): ColorMode =
let colors = toSeq(enumerate[ColorMode]())
colors.filter(c => $c == color).optLast.get(ColorMode.colorNever)
- let root = getAll(%%%"root").optLast.orElse(defaultConfig.rootOption)
- let db = getAll(%%%"dbpath").optLast.orElse(defaultConfig.dbOption)
- let cache = getAll(%%%"cachedir").optLast.orElse(defaultConfig.cacheOption)
- let gpg = getAll(%%%"gpgdir").optLast.orElse(defaultConfig.gpgOption)
+ let rootRel = getAll(%%%"root").optLast.orElse(defaultConfig.rootRelOption)
+ let dbRel = getAll(%%%"dbpath").optLast.orElse(defaultConfig.dbRelOption)
+ let cacheRel = getAll(%%%"cachedir").optLast.orElse(defaultConfig.cacheRelOption)
+ let gpgRel = getAll(%%%"gpgdir").optLast.orElse(defaultConfig.gpgRelOption)
let arch = getAll(%%%"arch").optLast.get(defaultConfig.arch)
let colorStr = getAll(%%%"color").optLast.get($defaultConfig.colorMode)
let color = getColor(colorStr)
@@ -362,7 +368,7 @@ proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig =
else:
var pgpKeyserver = none(string)
var file: File
- if file.open(gpg.get(sysConfDir & "/pacman.d/gnupg") & "/gpg.conf"):
+ if file.open(gpgRel.get(sysConfDir & "/pacman.d/gnupg").extendRel(sysroot) & "/gpg.conf"):
try:
while true:
let line = file.readLine()
@@ -374,19 +380,26 @@ proc obtainPacmanConfig*(args: seq[Argument]): PacmanConfig =
file.close()
pgpKeyserver)
- let config = PacmanConfig(rootOption: root, dbOption: db, cacheOption: cache, gpgOption: gpg,
+ let defaultRootRel = defaultConfig.rootRelOption.get("/")
+ let argsRootRel = rootRel.get("/")
+ let defaultRoot = defaultRootRel == argsRootRel
+
+ let config = PacmanConfig(sysrootOption: sysroot, rootRelOption: rootRel,
+ dbRelOption: dbRel, cacheRelOption: cacheRel, gpgRelOption: gpgRel,
dbs: defaultConfig.dbs, arch: arch, colorMode: color, debug: debug,
progressBar: progressBar, verbosePkgList: defaultConfig.verbosePkgList,
- pgpKeyserver: pgpKeyserver, ignorePkgs: ignorePkgs + defaultConfig.ignorePkgs,
+ pgpKeyserver: pgpKeyserver, defaultRoot: defaultRoot,
+ ignorePkgs: ignorePkgs + defaultConfig.ignorePkgs,
ignoreGroups: ignoreGroups + defaultConfig.ignoreGroups)
if config.dbs.find("aur") >= 0:
raise commandError(tr"repo '$#' is reserved by this program" % ["aur"],
colorNeeded = some(color.get))
- pacmanValidateAndThrow(("root", some(config.root), ArgumentType.long),
- ("dbpath", some(config.db), ArgumentType.long),
- ("arch", some(config.arch), ArgumentType.long),
- ("color", some(colorStr), ArgumentType.long))
+ pacmanValidateAndThrow((("sysroot", sysroot, ArgumentType.long), sysroot.isSome),
+ (("root", some(config.pacmanRootRel), ArgumentType.long), not defaultRoot),
+ (("dbpath", some(config.pacmanDbRel), ArgumentType.long), true),
+ (("arch", some(config.arch), ArgumentType.long), true),
+ (("color", some(colorStr), ArgumentType.long), true))
config