Skip to content

Commit

Permalink
Treat absence of prefix whitespace as section keys when reading ini f…
Browse files Browse the repository at this point in the history
…iles (#1029)
  • Loading branch information
trivikr authored Oct 13, 2023
1 parent d7f5cda commit 5bd4682
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-tips-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/shared-ini-file-loader": patch
---

Treat absence of prefix whitespace as section keys when reading ini files
81 changes: 55 additions & 26 deletions packages/shared-ini-file-loader/src/parseIni.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,63 @@ describe(parseIni.name, () => {
});
});

it("returns data from main section, and not subsection", () => {
const mockProfileDataWithSubSettings = {
key: "value",
subSection: { subKey: "subValue" },
};
const mockInput = getMockProfileContent(mockProfileName, mockProfileDataWithSubSettings);
expect(parseIni(mockInput)).toStrictEqual({
[mockProfileName]: {
key: "value",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subValue",
},
describe("returns data from main section, and not subsection", () => {
it("if subsection comes after section", () => {
const mockProfileDataWithSubSettings = {
key: "keyValue",
subSection: {
key: "keyValueInSubSection",
subKey: "subKeyValue",
},
};
const mockInput = getMockProfileContent(mockProfileName, mockProfileDataWithSubSettings);
expect(parseIni(mockInput)).toStrictEqual({
[mockProfileName]: {
key: "keyValue",
[["subSection", "key"].join(CONFIG_PREFIX_SEPARATOR)]: "keyValueInSubSection",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subKeyValue",
},
});

const mockProfileName2 = "mock_profile_name_2";
const mockProfileDataWithSubSettings2 = {
key: "keyValue2",
subSection: {
key: "keyValue2InSubSection",
subKey: "subKeyValue2",
},
};
const mockInput2 = getMockProfileContent(mockProfileName2, mockProfileDataWithSubSettings2);
expect(parseIni(`${mockInput}${mockInput2}`)).toStrictEqual({
[mockProfileName]: {
key: "keyValue",
[["subSection", "key"].join(CONFIG_PREFIX_SEPARATOR)]: "keyValueInSubSection",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subKeyValue",
},
[mockProfileName2]: {
key: "keyValue2",
[["subSection", "key"].join(CONFIG_PREFIX_SEPARATOR)]: "keyValue2InSubSection",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subKeyValue2",
},
});
});

const mockProfileName2 = "mock_profile_name_2";
const mockProfileDataWithSubSettings2 = {
key: "value2",
subSection: { subKey: "subValue2" },
};
const mockInput2 = getMockProfileContent(mockProfileName2, mockProfileDataWithSubSettings2);
expect(parseIni(`${mockInput}${mockInput2}`)).toStrictEqual({
[mockProfileName]: {
key: "value",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subValue",
},
[mockProfileName2]: {
key: "value2",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subValue2",
},
it("if subsection comes before section", () => {
const mockProfileDataWithSubSettings = {
subSection: {
key: "keyValueInSubSection",
subKey: "subKeyValue",
},
key: "keyValue",
};
const mockInput = getMockProfileContent(mockProfileName, mockProfileDataWithSubSettings);
expect(parseIni(mockInput)).toStrictEqual({
[mockProfileName]: {
[["subSection", "key"].join(CONFIG_PREFIX_SEPARATOR)]: "keyValueInSubSection",
[["subSection", "subKey"].join(CONFIG_PREFIX_SEPARATOR)]: "subKeyValue",
key: "keyValue",
},
});
});
});
});
Expand Down
18 changes: 11 additions & 7 deletions packages/shared-ini-file-loader/src/parseIni.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export const parseIni = (iniData: string): ParsedIniData => {
let currentSection: string | undefined;
let currentSubSection: string | undefined;

for (let line of iniData.split(/\r?\n/)) {
line = line.split(/(^|\s)[;#]/)[0].trim(); // remove comments and trim
const isSection: boolean = line[0] === "[" && line[line.length - 1] === "]";
for (const iniLine of iniData.split(/\r?\n/)) {
const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim(); // remove comments and trim
const isSection: boolean = trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]";
if (isSection) {
// New section found. Reset currentSection and currentSubSection.
currentSection = undefined;
currentSubSection = undefined;

const sectionName = line.substring(1, line.length - 1);
const sectionName = trimmedLine.substring(1, trimmedLine.length - 1);
const matches = prefixKeyRegex.exec(sectionName);
if (matches) {
const [, prefix, , name] = matches;
Expand All @@ -36,15 +36,19 @@ export const parseIni = (iniData: string): ParsedIniData => {
throw new Error(`Found invalid profile name "${sectionName}"`);
}
} else if (currentSection) {
const indexOfEqualsSign = line.indexOf("=");
const indexOfEqualsSign = trimmedLine.indexOf("=");
if (![0, -1].includes(indexOfEqualsSign)) {
const [name, value]: [string, string] = [
line.substring(0, indexOfEqualsSign).trim(),
line.substring(indexOfEqualsSign + 1).trim(),
trimmedLine.substring(0, indexOfEqualsSign).trim(),
trimmedLine.substring(indexOfEqualsSign + 1).trim(),
];
if (value === "") {
currentSubSection = name;
} else {
if (currentSubSection && iniLine.trimStart() === iniLine) {
// Reset currentSubSection if there is no whitespace
currentSubSection = undefined;
}
map[currentSection] = map[currentSection] || {};
const key = currentSubSection ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR) : name;
map[currentSection][key] = value;
Expand Down

0 comments on commit 5bd4682

Please sign in to comment.