Skip to content

Commit

Permalink
Merge pull request #50 from blackflux/dev
Browse files Browse the repository at this point in the history
[Gally]: master <- dev
  • Loading branch information
simlu committed Mar 16, 2019
2 parents 87a84f5 + 414043d commit 1ec6f15
Show file tree
Hide file tree
Showing 27 changed files with 276 additions and 45 deletions.
1 change: 1 addition & 0 deletions .depunusedignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eslint
2 changes: 1 addition & 1 deletion .idea/robo-config.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"babel-eslint": "10.0.1",
"chai": "4.2.0",
"coveralls": "3.0.3",
"js-gardener": "1.38.2",
"eslint": "5.15.1",
"js-gardener": "1.38.3",
"nyc": "13.3.0",
"semantic-release": "15.13.3",
"tmp": "0.0.33"
Expand Down Expand Up @@ -94,6 +95,7 @@
"joi": "14.3.1",
"lodash.clonedeep": "4.5.0",
"lodash.difference": "4.5.0",
"object-deep-contain": "1.0.4",
"object-scan": "5.0.3",
"smart-fs": "1.3.0"
}
Expand Down
5 changes: 5 additions & 0 deletions src/configs/jetbrains/@common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"configs": [
"jetbrains/exclude-coverage-folder"
]
}
13 changes: 13 additions & 0 deletions src/configs/jetbrains/exclude-coverage-folder.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"target": ".idea/${projectName}.iml",
"format": "xml",
"strategy": "xml-merge",
"snippets": [
{
"name": "exclude-folder-from-module",
"variables": {
"folder": "coverage"
}
}
]
}
7 changes: 7 additions & 0 deletions src/configs/jetbrains/snippets/exclude-folder-from-module.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<module>
<component>
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/${folder}"/>
</content>
</component>
</module>
10 changes: 8 additions & 2 deletions src/util/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const strategies = require('./strategies');

const configSchema = Joi.object().keys({
target: Joi.string(),
format: Joi.string().allow(null),
strategy: Joi.string().valid(...Object.keys(strategies)),
snippets: Joi.array().items(
Joi.string(),
Expand All @@ -20,7 +21,7 @@ const configSchema = Joi.object().keys({
).min(1),
configs: Joi.array().items(Joi.string())
})
.and('target', 'strategy', 'snippets')
.and('target', 'strategy', 'snippets', 'format')
.xor('target', 'configs')
.unknown(false)
.required();
Expand All @@ -34,7 +35,7 @@ const loadSnippet = (snippetDir, snippetName, config, snippetVars) => {

const fileName = sls.guessFile(path.join(snippetDir, snippetName));
assert(fileName !== null, `Invalid Snippet File Name: ${snippetName}`);
const snippet = sls.smartRead(fileName);
const snippet = sls.smartRead(fileName, { treatAs: config.format });

return populateVars(snippet, snippetVars, false);
};
Expand All @@ -50,13 +51,17 @@ module.exports.loadConfig = (configName, variables) => {
return null;
}
const config = sls.smartRead(configFilePath);
if (config.target !== undefined) {
config.format = config.format || null;
}

assert(Joi.validate(config, configSchema).error === null, `Invalid Config Detected: ${configName}`);
assert(configName.includes('/@') === (config.configs !== undefined), `Invalid Config Name Detected: ${configName}`);

if (typeof config.target === 'string') {
// load and merge config snippets into config
const snippetDir = path.join(__dirname, '..', 'configs', configName.split('/')[0], 'snippets');
config.target = populateVars([config.target], variables, true)[0];
config.toWrite = deepmerge.all(config.snippets
.map(m => (typeof m === 'string' ? [m, {}] : [m.name, m.variables]))
.map(([snippetName, snippetVars]) => [snippetName, populateVars(snippetVars, variables, true)])
Expand All @@ -73,6 +78,7 @@ module.exports.applyConfig = (config, projectRoot) => {

const target = path.join(projectRoot, config.target);
return sls.smartWrite(target, config.toWrite, {
treatAs: config.format,
mergeStrategy: strategies[config.strategy]
});
};
2 changes: 2 additions & 0 deletions src/util/strategies.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const assert = require('assert');
const xmlMerge = require('./xml-merge');

module.exports = {
'merge-below-title': (existing, changeset) => {
Expand Down Expand Up @@ -32,5 +33,6 @@ module.exports = {
return changeset.concat(existing);
},
'merge-shallow': (existing, changeset) => Object.assign(existing, changeset),
'xml-merge': (existing, changeset) => xmlMerge(existing, changeset),
overwrite: (existing, changeset) => changeset
};
42 changes: 42 additions & 0 deletions src/util/xml-merge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const objectDeepContain = require('object-deep-contain');

const mergeRec = (target, changeset) => {
if (changeset === undefined) {
return target;
}

const isArray = Array.isArray(target);
if (isArray !== Array.isArray(changeset)) {
return changeset;
}

if (isArray) {
let next = 0;
for (let idx = 0; idx < target.length && next < changeset.length; idx += 1) {
const targetElement = target[idx];
const toInsert = changeset[next];

if (objectDeepContain(
targetElement,
Object
.entries(toInsert)
.reduce((p, [k, v]) => Object.assign(p, k === 'elements' ? {} : { [k]: v }), {})
)) {
// eslint-disable-next-line no-param-reassign
target[idx] = mergeRec(targetElement, toInsert);
next += 1;
}
}
target.push(...changeset.slice(next));
return target;
}

if (target instanceof Object && changeset instanceof Object) {
return [...new Set(Object.keys(target).concat(Object.keys(changeset)))]
.reduce((p, k) => Object.assign(p, { [k]: mergeRec(target[k], changeset[k]) }), {});
}

return changeset;
};

module.exports = (target, changeset) => Object.assign(target, { data: mergeRec(target.data, changeset.data) });
6 changes: 5 additions & 1 deletion test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ const robo = require('../src/index');

it('Executing Configuration', () => {
expect(robo({
configs: ['assorted/@npm-opensource'],
configs: [
'assorted/@npm-opensource',
'jetbrains/@common'
],
variables: {
repoKey: 'blackflux/robo-config',
repoName: 'robo-config',
projectName: 'robo-config',
owner: 'simlu',
authorName: 'Lukas Siemon',
mergeBot: 'MrsFlux'
Expand Down
51 changes: 51 additions & 0 deletions test/util/xml-merge.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const fs = require('fs');
const path = require('path');
const expect = require('chai').expect;
const tmp = require('tmp');
const sfs = require('smart-fs');
const xmlMerge = require('../../src/util/xml-merge');

describe('Integration xml-merge.js', () => {
fs.readdirSync(path.join(__dirname, 'xml-merge'))
.forEach((f) => {
it(`Testing '${f}'`, () => {
const target = sfs.smartRead(path.join(__dirname, 'xml-merge', f, 'target.xml'));
const changeset = sfs.smartRead(path.join(__dirname, 'xml-merge', f, 'changeset.xml'));
const result = sfs.smartRead(path.join(__dirname, 'xml-merge', f, 'result.xml'));
const merged = xmlMerge(target, changeset);
expect(result).to.deep.equal(merged);
});
});
});

describe('Unit xml-merge.js', () => {
let dir;
beforeEach(() => {
dir = tmp.dirSync({ keep: false, unsafeCleanup: true }).name;
});

const executeTest = (target, changeset, result) => {
fs.writeFileSync(path.join(dir, 'target.xml'), target);
fs.writeFileSync(path.join(dir, 'changeset.xml'), changeset);
fs.writeFileSync(path.join(dir, 'result.xml'), result);

const merged = xmlMerge(
sfs.smartRead(path.join(dir, 'target.xml')),
sfs.smartRead(path.join(dir, 'changeset.xml'))
);
expect(merged).to.deep.equal(sfs.smartRead(path.join(dir, 'result.xml')));
};

it('Test Simple Merge', () => {
executeTest('<a/>', '<b/>', '<a/><b/>');
executeTest('<r><a/></r>', '<r><b/></r>', '<r><a/><b/></r>');
});

it('Test Header Merge', () => {
executeTest(
'<?xml version="1.0" ?>',
'<?xml encoding="UTF-8" ?>',
'<?xml version="1.0" encoding="UTF-8" ?>'
);
});
});
5 changes: 5 additions & 0 deletions test/util/xml-merge/append/changeset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<root>
<b y="4"/>
<a y="5"/>
<b y="6"/>
</root>
8 changes: 8 additions & 0 deletions test/util/xml-merge/append/result.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<root>
<a x="1"/>
<b x="2"/>
<a x="3"/>
<b y="4"/>
<a y="5"/>
<b y="6"/>
</root>
5 changes: 5 additions & 0 deletions test/util/xml-merge/append/target.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<root>
<a x="1"/>
<b x="2"/>
<a x="3"/>
</root>
1 change: 1 addition & 0 deletions test/util/xml-merge/header/changeset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" ?>
2 changes: 2 additions & 0 deletions test/util/xml-merge/header/result.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<empty />
2 changes: 2 additions & 0 deletions test/util/xml-merge/header/target.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml standalone="yes" ?>
<empty />
7 changes: 7 additions & 0 deletions test/util/xml-merge/no-change/changeset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<module>
<component>
<orderEntry type="B">
<test/>
</orderEntry>
</component>
</module>
8 changes: 8 additions & 0 deletions test/util/xml-merge/no-change/result.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<module>
<component>
<orderEntry type="A"/>
<orderEntry type="B">
<test/>
</orderEntry>
</component>
</module>
8 changes: 8 additions & 0 deletions test/util/xml-merge/no-change/target.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<module>
<component>
<orderEntry type="A"/>
<orderEntry type="B">
<test/>
</orderEntry>
</component>
</module>
7 changes: 7 additions & 0 deletions test/util/xml-merge/target-first/changeset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<module>
<component>
<orderEntry type="A">
<test/>
</orderEntry>
</component>
</module>
7 changes: 7 additions & 0 deletions test/util/xml-merge/target-first/result.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<module>
<component>
<orderEntry type="A">
<test/>
</orderEntry>
</component>
</module>
5 changes: 5 additions & 0 deletions test/util/xml-merge/target-first/target.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<module>
<component>
<orderEntry type="A"/>
</component>
</module>
7 changes: 7 additions & 0 deletions test/util/xml-merge/target-second/changeset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<module>
<component>
<orderEntry type="B">
<test/>
</orderEntry>
</component>
</module>
8 changes: 8 additions & 0 deletions test/util/xml-merge/target-second/result.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<module>
<component>
<orderEntry type="A"/>
<orderEntry type="B">
<test/>
</orderEntry>
</component>
</module>
6 changes: 6 additions & 0 deletions test/util/xml-merge/target-second/target.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<module>
<component>
<orderEntry type="A"/>
<orderEntry type="B"/>
</component>
</module>
Loading

0 comments on commit 1ec6f15

Please sign in to comment.