Skip to content

Commit

Permalink
Clean up ignore files during migration (#94)
Browse files Browse the repository at this point in the history
This should leave repos migrated from `seek-module-toolkit` and pre-#58
ignore files in a better state instead of littering old patterns
everywhere.
  • Loading branch information
72636c authored Jun 22, 2020
1 parent 205f27d commit 573ea6e
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-jeans-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'skuba': patch
---

**configure:** Clean up ignore files during migration
32 changes: 26 additions & 6 deletions src/cli/configure/processing/__snapshots__/ignoreFile.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

exports[`mergeWithIgnoreFile empty provided 1`] = `
"# managed by skuba
node_modules
node_modules*/
# end managed by skuba
"
`;

exports[`mergeWithIgnoreFile identical 1`] = `
"# managed by skuba
node_modules
node_modules*/
# end managed by skuba
"
`;
Expand All @@ -19,17 +19,37 @@ exports[`mergeWithIgnoreFile provided with managed section and additional lines
.vscode
# managed by skuba
node_modules
node_modules*/
# end managed by skuba
.DS_Store
node_modules
"
`;

exports[`mergeWithIgnoreFile provided with managed section and fully superseded config 1`] = `
"# managed by skuba
node_modules*/
.DS_Store
# end managed by skuba
"
`;

exports[`mergeWithIgnoreFile provided with managed section and partially superseded config 1`] = `
"# managed by skuba
node_modules*/
.DS_Store
# end managed by skuba
system32
*.zip
"
`;

exports[`mergeWithIgnoreFile provided with no managed section 1`] = `
"# managed by skuba
node_modules
node_modules*/
# end managed by skuba
.DS_Store
Expand All @@ -38,7 +58,7 @@ node_modules

exports[`mergeWithIgnoreFile provided with outdated managed section 1`] = `
"# managed by skuba
node_modules
node_modules*/
.DS_Store
# end managed by skuba
"
Expand All @@ -49,7 +69,7 @@ exports[`mergeWithIgnoreFile provided with outdated managed section and addition
.vscode
# managed by skuba
node_modules
node_modules*/
.DS_Store
# end managed by skuba
Expand Down
29 changes: 26 additions & 3 deletions src/cli/configure/processing/ignoreFile.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
import { mergeWithIgnoreFile } from './ignoreFile';
import { generateSimpleVariants, mergeWithIgnoreFile } from './ignoreFile';

describe('generateSimpleVariants', () => {
it.each([
['variant path', ['/lib*/'], ['/lib*/', '/lib/', '/lib', 'lib/', 'lib']],
['non-variant path', ['lib'], ['lib']],
['duplicate patterns', ['lib', 'lib'], ['lib']],
['file extension', ['*.tgz'], ['*.tgz', '.tgz']],
['potential empty string', ['/'], ['/']],
['empty string', [''], []],
])('handles %s', (_, pattern, expected) =>
expect(generateSimpleVariants(pattern)).toEqual(new Set(expected)),
);
});

describe('mergeWithIgnoreFile', () => {
const baseTemplate =
'# managed by skuba\nnode_modules\n# end managed by skuba\n';
'# managed by skuba\nnode_modules*/\n# end managed by skuba\n';
const updatedBaseTemplate =
'# managed by skuba\nnode_modules\n.DS_Store\n# end managed by skuba\n';
'# managed by skuba\nnode_modules*/\n.DS_Store\n# end managed by skuba\n';

const cases = [
['empty provided', baseTemplate, ''],

['provided with no managed section', baseTemplate, '.DS_Store\n'],
[
'provided with managed section and partially superseded config',
updatedBaseTemplate,
'system32\n\n.DS_Store\nnode_modules/\n\n*.zip\n',
],
[
'provided with managed section and fully superseded config',
updatedBaseTemplate,
'\r\n\nnode_modules\r\nnode_modules_bak',
],
[
'provided with outdated managed section',
updatedBaseTemplate,
Expand Down
62 changes: 55 additions & 7 deletions src/cli/configure/processing/ignoreFile.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,69 @@
/**
* Patterns that are superseded by skuba's bundled ignore file patterns and are
* non-trivial to derive using e.g. `generateSimpleVariants`.
*/
const OUTDATED_PATTERNS = ['node_modules_bak/', 'tmp-*/'];

const ASTERISKS = /\*/g;
const LEADING_SLASH = /^\//;
const TRAILING_SLASH = /\/$/;

/**
* Generate simple variants of an ignore pattern for exact matching purposes.
*
* Note that these patterns are not actually equivalent (e.g. `lib` matches more
* than `lib/`) but they generally represent the same _intent_.
*/
export const generateSimpleVariants = (patterns: string[]) => {
const set = new Set<string>();

for (const pattern of patterns) {
const deAsterisked = pattern.replace(ASTERISKS, '');

set.add(pattern);
set.add(deAsterisked);
set.add(deAsterisked.replace(LEADING_SLASH, ''));
set.add(deAsterisked.replace(TRAILING_SLASH, ''));
set.add(
deAsterisked.replace(LEADING_SLASH, '').replace(TRAILING_SLASH, ''),
);
}

set.delete('');

return set;
};

export const mergeWithIgnoreFile = (rawTemplateFile: string) => {
const templateFile = rawTemplateFile.trim();

return (inputFile?: string) => {
if (typeof inputFile === 'undefined') {
const templatePatterns = generateSimpleVariants([
...OUTDATED_PATTERNS,
...templateFile.split('\n').map((line) => line.trim()),
]);

return (rawInputFile?: string) => {
if (typeof rawInputFile === 'undefined') {
return `${templateFile}\n`;
}

const replacedFile = inputFile.replace(
/# managed by skuba[\s\S]*# end managed by skuba/,
templateFile,
);
const replacedFile = rawInputFile
.replace(/\r?\n/g, '\n')
.replace(/# managed by skuba[\s\S]*# end managed by skuba/, templateFile);

if (replacedFile.includes(templateFile)) {
return replacedFile;
}

const outputFile = [templateFile, inputFile.trim()].join('\n\n').trim();
// Crunch the existing lines of a non-skuba config.
const migratedFile = replacedFile
.split('\n')
.filter((line) => !templatePatterns.has(line))
.join('\n')
.replace(/\n{3,}/g, '\n\n')
.trim();

const outputFile = [templateFile, migratedFile].join('\n\n').trim();

return `${outputFile}\n`;
};
Expand Down

0 comments on commit 573ea6e

Please sign in to comment.