mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
TERMINAL: Prevent recursive aliases from being resolved. (#741)
This commit is contained in:
parent
51b03003f6
commit
93235570d0
64
src/Alias.ts
64
src/Alias.ts
@ -65,39 +65,51 @@ export function removeAlias(name: string): boolean {
|
|||||||
/**
|
/**
|
||||||
* Returns the original string with any aliases substituted in.
|
* Returns the original string with any aliases substituted in.
|
||||||
* Aliases are only applied to "whole words", one level deep
|
* Aliases are only applied to "whole words", one level deep
|
||||||
|
* @param origCommand the original command string
|
||||||
*/
|
*/
|
||||||
export function substituteAliases(origCommand: string): string {
|
export function substituteAliases(origCommand: string): string {
|
||||||
|
return applyAliases(origCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively evaluates aliases and applies them to the command string,
|
||||||
|
* unless there are any reference loops or the reference chain is too deep
|
||||||
|
* @param origCommand the original command string
|
||||||
|
* @param depth the current recursion depth
|
||||||
|
* @param currentlyProcessingAliases any aliases that have been applied in the recursive evaluation leading to this point
|
||||||
|
* @return { string } the provided command with all of its referenced aliases evaluated
|
||||||
|
*/
|
||||||
|
function applyAliases(origCommand: string, depth = 0, currentlyProcessingAliases: string[] = []) {
|
||||||
|
if (!origCommand) {
|
||||||
|
return origCommand;
|
||||||
|
}
|
||||||
const commandArray = origCommand.split(" ");
|
const commandArray = origCommand.split(" ");
|
||||||
if (commandArray.length > 0) {
|
|
||||||
// For the alias and unalias commands, don't substitute
|
// Do not apply aliases when defining a new alias
|
||||||
if (commandArray[0] === "unalias" || commandArray[0] === "alias") {
|
if (commandArray[0] === "unalias" || commandArray[0] === "alias") {
|
||||||
return commandArray.join(" ");
|
return commandArray.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
let somethingSubstituted = true;
|
// First get non-global aliases, and recursively apply them
|
||||||
let depth = 0;
|
// (unless there are any reference loops or the reference chain is too deep)
|
||||||
let lastAlias;
|
const localAlias = Aliases.get(commandArray[0]);
|
||||||
|
if (localAlias && !currentlyProcessingAliases.includes(localAlias)) {
|
||||||
|
const appliedAlias = applyAliases(localAlias, depth + 1, [commandArray[0], ...currentlyProcessingAliases]);
|
||||||
|
commandArray.splice(0, 1, ...appliedAlias.split(" "));
|
||||||
|
}
|
||||||
|
|
||||||
while (somethingSubstituted && depth < 10) {
|
// Once local aliasing is complete (or if none are present) handle any global aliases
|
||||||
depth++;
|
const processedCommands = commandArray.reduce((resolvedCommandArray: string[], command) => {
|
||||||
somethingSubstituted = false;
|
const globalAlias = GlobalAliases.get(command);
|
||||||
const alias = Aliases.get(commandArray[0])?.split(" ");
|
if (globalAlias && !currentlyProcessingAliases.includes(globalAlias)) {
|
||||||
if (alias !== undefined) {
|
const appliedAlias = applyAliases(globalAlias, depth + 1, [command, ...currentlyProcessingAliases]);
|
||||||
somethingSubstituted = true;
|
resolvedCommandArray.push(appliedAlias);
|
||||||
commandArray.splice(0, 1, ...alias);
|
} else {
|
||||||
//commandArray[0] = alias;
|
// If there is no alias, or if the alias has a circular reference, leave the command as-is
|
||||||
|
resolvedCommandArray.push(command);
|
||||||
}
|
}
|
||||||
for (let i = 0; i < commandArray.length; ++i) {
|
return resolvedCommandArray;
|
||||||
const alias = GlobalAliases.get(commandArray[i])?.split(" ");
|
}, []);
|
||||||
if (alias !== undefined && (commandArray[i] != lastAlias || somethingSubstituted)) {
|
|
||||||
somethingSubstituted = true;
|
return processedCommands.join(" ");
|
||||||
lastAlias = commandArray[i];
|
|
||||||
commandArray.splice(i, 1, ...alias);
|
|
||||||
i += alias.length - 1;
|
|
||||||
//commandArray[i] = alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return commandArray.join(" ");
|
|
||||||
}
|
}
|
||||||
|
52
test/jest/Alias/Alias.test.ts
Normal file
52
test/jest/Alias/Alias.test.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { substituteAliases, parseAliasDeclaration } from "../../../src/Alias";
|
||||||
|
describe("substituteAliases Tests", () => {
|
||||||
|
it("Should gracefully handle recursive local aliases", () => {
|
||||||
|
parseAliasDeclaration("recursiveAlias=b");
|
||||||
|
parseAliasDeclaration("b=c");
|
||||||
|
parseAliasDeclaration("c=d");
|
||||||
|
parseAliasDeclaration("d=recursiveAlias");
|
||||||
|
|
||||||
|
const result = substituteAliases("recursiveAlias");
|
||||||
|
expect(result).toEqual("d");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should only change local aliases if they are the start of the command", () => {
|
||||||
|
parseAliasDeclaration("a=b");
|
||||||
|
parseAliasDeclaration("b=c");
|
||||||
|
parseAliasDeclaration("c=d");
|
||||||
|
parseAliasDeclaration("d=e");
|
||||||
|
|
||||||
|
const result = substituteAliases("a b c d");
|
||||||
|
expect(result).toEqual("e b c d");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should gracefully handle recursive global aliases", () => {
|
||||||
|
parseAliasDeclaration("a=b", true);
|
||||||
|
parseAliasDeclaration("b=c", true);
|
||||||
|
parseAliasDeclaration("c=d", true);
|
||||||
|
parseAliasDeclaration("d=a", true);
|
||||||
|
|
||||||
|
const result = substituteAliases("a b c d");
|
||||||
|
expect(result).toEqual("d a b c");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should gracefully handle recursive mixed local and global aliases", () => {
|
||||||
|
parseAliasDeclaration("recursiveAlias=b", true);
|
||||||
|
parseAliasDeclaration("b=c", false);
|
||||||
|
parseAliasDeclaration("c=d", true);
|
||||||
|
parseAliasDeclaration("d=recursiveAlias", false);
|
||||||
|
|
||||||
|
const result = substituteAliases("recursiveAlias");
|
||||||
|
expect(result).toEqual("d");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should replace chained aliases", () => {
|
||||||
|
parseAliasDeclaration("a=b", true);
|
||||||
|
parseAliasDeclaration("b=c", true);
|
||||||
|
parseAliasDeclaration("c=d", true);
|
||||||
|
parseAliasDeclaration("d=e", true);
|
||||||
|
|
||||||
|
const result = substituteAliases("a");
|
||||||
|
expect(result).toEqual("e");
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user