taler-util: set [PATH] defaults
This commit is contained in:
parent
3d6cff9c84
commit
896841aec5
@ -170,6 +170,39 @@ const sandcastleCli = testingCli.subcommand("sandcastleArgs", "sandcastle", {
|
||||
help: "Subcommands for handling GNU Taler sandcastle deployments.",
|
||||
});
|
||||
|
||||
const configCli = testingCli.subcommand("configArgs", "config", {
|
||||
help: "Subcommands for handling the Taler configuration.",
|
||||
});
|
||||
|
||||
configCli.subcommand("show", "show").action(async (args) => {
|
||||
const config = Configuration.load();
|
||||
const cfgStr = config.stringify({
|
||||
diagnostics: true,
|
||||
});
|
||||
console.log(cfgStr);
|
||||
});
|
||||
|
||||
configCli
|
||||
.subcommand("get", "get")
|
||||
.requiredArgument("section", clk.STRING)
|
||||
.requiredArgument("option", clk.STRING)
|
||||
.flag("file", ["-f"])
|
||||
.action(async (args) => {
|
||||
const config = Configuration.load();
|
||||
let res;
|
||||
if (args.get.file) {
|
||||
res = config.getString(args.get.section, args.get.option);
|
||||
} else {
|
||||
res = config.getPath(args.get.section, args.get.option);
|
||||
}
|
||||
if (res.isDefined()) {
|
||||
console.log(res.value);
|
||||
} else {
|
||||
console.warn("not found");
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
const deploymentCli = testingCli.subcommand("deploymentArgs", "deployment", {
|
||||
help: "Subcommands for handling GNU Taler deployments.",
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of GNU Taler
|
||||
(C) 2020 Taler Systems S.A.
|
||||
(C) 2020-2023 Taler Systems S.A.
|
||||
|
||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -40,12 +40,22 @@ export class ConfigError extends Error {
|
||||
}
|
||||
|
||||
enum EntryOrigin {
|
||||
// From a default file
|
||||
Default = 1,
|
||||
// Loaded from file or string
|
||||
Loaded = 2,
|
||||
// Changed after loading
|
||||
Changed = 3,
|
||||
/**
|
||||
* From a default file.
|
||||
*/
|
||||
DefaultFile = 1,
|
||||
/**
|
||||
* From a system/installation specific default value.
|
||||
*/
|
||||
DefaultSystem = 2,
|
||||
/**
|
||||
* Loaded from file or string
|
||||
*/
|
||||
Loaded = 3,
|
||||
/**
|
||||
* Changed after loading
|
||||
*/
|
||||
Changed = 4,
|
||||
}
|
||||
|
||||
interface Entry {
|
||||
@ -169,12 +179,12 @@ export function pathsub(
|
||||
|
||||
const r = lookup(inner, depth + 1);
|
||||
if (r !== undefined) {
|
||||
s = s.substr(0, start) + r + s.substr(p + 1);
|
||||
s = s.substring(0, start) + r + s.substring(p + 1);
|
||||
l = start + r.length;
|
||||
continue;
|
||||
} else if (defaultValue !== undefined) {
|
||||
const resolvedDefault = pathsub(defaultValue, lookup, depth + 1);
|
||||
s = s.substr(0, start) + resolvedDefault + s.substr(p + 1);
|
||||
s = s.substring(0, start) + resolvedDefault + s.substring(p + 1);
|
||||
l = start + resolvedDefault.length;
|
||||
continue;
|
||||
}
|
||||
@ -186,7 +196,7 @@ export function pathsub(
|
||||
if (m && m[0]) {
|
||||
const r = lookup(m[0], depth + 1);
|
||||
if (r !== undefined) {
|
||||
s = s.substr(0, l) + r + s.substr(l + 1 + m[0].length);
|
||||
s = s.substring(0, l) + r + s.substring(l + 1 + m[0].length);
|
||||
l = l + r.length;
|
||||
continue;
|
||||
}
|
||||
@ -492,7 +502,9 @@ export class Configuration {
|
||||
value: val,
|
||||
sourceFile: opts.filename ?? "<unknown>",
|
||||
sourceLine: lineNo,
|
||||
origin: isDefaultSource ? EntryOrigin.Default : EntryOrigin.Loaded,
|
||||
origin: isDefaultSource
|
||||
? EntryOrigin.DefaultFile
|
||||
: EntryOrigin.Loaded,
|
||||
};
|
||||
continue;
|
||||
}
|
||||
@ -535,6 +547,23 @@ export class Configuration {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a string value to a value from default locations.
|
||||
*/
|
||||
private setStringSystemDefault(
|
||||
section: string,
|
||||
option: string,
|
||||
value: string,
|
||||
): void {
|
||||
const sec = this.provideSection(section);
|
||||
sec.entries[option.toUpperCase()] = {
|
||||
value,
|
||||
sourceLine: 0,
|
||||
sourceFile: "<unknown>",
|
||||
origin: EntryOrigin.DefaultSystem,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upper-cased section names.
|
||||
*/
|
||||
@ -595,7 +624,7 @@ export class Configuration {
|
||||
lookupVariable(x: string, depth: number = 0): string | undefined {
|
||||
// We loop up options in PATHS in upper case, as option names
|
||||
// are case insensitive
|
||||
const val = this.findEntry("PATHS", x)?.value;
|
||||
let val = this.findEntry("PATHS", x)?.value;
|
||||
if (val !== undefined) {
|
||||
return pathsub(val, (v, d) => this.lookupVariable(v, d), depth);
|
||||
}
|
||||
@ -623,21 +652,54 @@ export class Configuration {
|
||||
}
|
||||
|
||||
private loadDefaults(): void {
|
||||
let bc = process.env["TALER_BASE_CONFIG"];
|
||||
if (!bc) {
|
||||
let baseConfigDir = process.env["TALER_BASE_CONFIG"];
|
||||
if (!baseConfigDir) {
|
||||
/* Try to locate the configuration based on the location
|
||||
* of the taler-config binary. */
|
||||
const path = which("taler-config");
|
||||
if (path) {
|
||||
bc = nodejs_fs.realpathSync(
|
||||
baseConfigDir = nodejs_fs.realpathSync(
|
||||
nodejs_path.dirname(path) + "/../share/taler/config.d",
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!bc) {
|
||||
bc = "/usr/share/taler/config.d";
|
||||
if (!baseConfigDir) {
|
||||
baseConfigDir = "/usr/share/taler/config.d";
|
||||
}
|
||||
this.loadDefaultsFromDir(bc);
|
||||
|
||||
let installPrefix = process.env["TALER_PREFIX"];
|
||||
if (!installPrefix) {
|
||||
/* Try to locate install path based on the location
|
||||
* of the taler-config binary. */
|
||||
const path = which("taler-config");
|
||||
if (path) {
|
||||
installPrefix = nodejs_fs.realpathSync(
|
||||
nodejs_path.dirname(path) + "/..",
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!installPrefix) {
|
||||
installPrefix = "/usr";
|
||||
}
|
||||
|
||||
this.setStringSystemDefault(
|
||||
"PATHS",
|
||||
"LIBEXECDIR",
|
||||
`${installPrefix}/taler/libexec/`,
|
||||
);
|
||||
this.setStringSystemDefault(
|
||||
"PATHS",
|
||||
"DOCDIR",
|
||||
`${installPrefix}/share/doc/taler/`,
|
||||
);
|
||||
this.setStringSystemDefault("PATHS", "ICONDIR", `${installPrefix}/share/icons/`);
|
||||
this.setStringSystemDefault("PATHS", "LOCALEDIR", `${installPrefix}/share/locale/`);
|
||||
this.setStringSystemDefault("PATHS", "PREFIX", `${installPrefix}/`);
|
||||
this.setStringSystemDefault("PATHS", "BINDIR", `${installPrefix}/bin`);
|
||||
this.setStringSystemDefault("PATHS", "LIBDIR", `${installPrefix}/lib/taler/`);
|
||||
this.setStringSystemDefault("PATHS", "DATADIR", `${installPrefix}/share/taler/`);
|
||||
|
||||
this.loadDefaultsFromDir(baseConfigDir);
|
||||
}
|
||||
|
||||
getDefaultConfigFilename(): string | undefined {
|
||||
@ -698,7 +760,11 @@ export class Configuration {
|
||||
let headerWritten = false;
|
||||
for (const optionName of Object.keys(sec.entries)) {
|
||||
const entry = this.sectionMap[sectionName].entries[optionName];
|
||||
if (opts.excludeDefaults && entry.origin === EntryOrigin.Default) {
|
||||
if (
|
||||
opts.excludeDefaults &&
|
||||
(entry.origin === EntryOrigin.DefaultSystem ||
|
||||
entry.origin === EntryOrigin.DefaultFile)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (!headerWritten) {
|
||||
@ -711,7 +777,16 @@ export class Configuration {
|
||||
}
|
||||
if (entry !== undefined) {
|
||||
if (opts.diagnostics) {
|
||||
switch (entry.origin) {
|
||||
case EntryOrigin.DefaultFile:
|
||||
case EntryOrigin.Changed:
|
||||
case EntryOrigin.Loaded:
|
||||
s += `# ${entry.sourceFile}:${entry.sourceLine}\n`;
|
||||
break;
|
||||
case EntryOrigin.DefaultSystem:
|
||||
s += `# (system/installation default)\n`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s += `${optionName} = ${entry.value}\n`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user