Skip to content

Commit 7b556f0

Browse files
Merge pull request #585 from pattern-lab/bugfix/incremental-builds
Bugfix/incremental builds
2 parents 6fac7d5 + a1d11c9 commit 7b556f0

File tree

5 files changed

+80
-24
lines changed

5 files changed

+80
-24
lines changed

core/lib/changes_hunter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ ChangesHunter.prototype = {
4040
pattern.compileState = CompileState.CLEAN;
4141
}
4242
} catch (e) {
43-
// Output does not exist yet, needs recompile
43+
// Output does not exist yet, force recompile
44+
pattern.compileState = CompileState.NEEDS_REBUILD;
4445
}
4546

4647
let node = patternlab.graph.node(pattern);

core/lib/pattern_assembler.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ var path = require('path'),
1515
ch = require('./changes_hunter'),
1616
JSON5 = require('json5');
1717

18-
var markdown_parser = new mp();
19-
var changes_hunter = new ch();
18+
const markdown_parser = new mp();
19+
const changes_hunter = new ch();
2020

2121
var pattern_assembler = function () {
2222
// HELPER FUNCTIONS
@@ -155,6 +155,8 @@ var pattern_assembler = function () {
155155

156156
try {
157157
var markdownFileName = path.resolve(patternlab.config.paths.source.patterns, currentPattern.subdir, currentPattern.fileName + ".md");
158+
changes_hunter.checkLastModified(currentPattern, markdownFileName);
159+
158160
var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8');
159161

160162
var markdownObject = markdown_parser.parse(markdownFileContents);

core/lib/pattern_graph.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ var nodeName =
5555

5656
PatternGraph.prototype = {
5757

58+
/**
59+
* Synchronizes the graph nodes with the set of all known patterns.
60+
* For instance when a pattern is deleted or moved, it might still have a node from the serialized
61+
* JSON, but there is no source pattern.
62+
*
63+
* @see {@link https://github.com/pattern-lab/patternlab-node/issues/580|Issue #580}
64+
*/
65+
sync: function () {
66+
// Remove any patterns that are in the graph data, but that haven't been discovered when
67+
// walking all patterns iteratively
68+
const nodesToRemove = this.nodes().filter(n => !this.patterns.has(n));
69+
nodesToRemove.forEach(n => this.remove(n));
70+
return nodesToRemove;
71+
},
72+
5873
/**
5974
* Creates an independent copy of the graph where nodes and edges can be modified without
6075
* affecting the source.
@@ -362,7 +377,7 @@ PatternGraph.resolveJsonGraphFile = function (patternlab, file) {
362377
PatternGraph.loadFromFile = function (patternlab, file) {
363378
const jsonGraphFile = this.resolveJsonGraphFile(patternlab, file);
364379

365-
// File is fresh, so simply constuct an empty graph in memory
380+
// File is fresh, so simply construct an empty graph in memory
366381
if (!fs.existsSync(jsonGraphFile)) {
367382
return PatternGraph.empty();
368383
}

core/lib/patternlab.js

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -438,10 +438,50 @@ var patternlab_engine = function (config) {
438438
return true;
439439
}
440440

441+
/**
442+
* If a graph was serialized and then {@code deletePatternDir == true}, there is a mismatch in the
443+
* pattern metadata and not all patterns might be recompiled.
444+
* For that reason an empty graph is returned in this case, so every pattern will be flagged as
445+
* "needs recompile". Otherwise the pattern graph is loaded from the meta data.
446+
*
447+
* @param patternlab
448+
* @param {boolean} deletePatternDir When {@code true}, an empty graph is returned
449+
* @return {PatternGraph}
450+
*/
451+
function loadPatternGraph(deletePatternDir) {
452+
// Sanity check to prevent problems when code is refactored
453+
if (deletePatternDir) {
454+
return PatternGraph.empty();
455+
}
456+
return PatternGraph.loadFromFile(patternlab);
457+
}
458+
441459
function buildPatterns(deletePatternDir) {
442460

443461
patternlab.events.emit('patternlab-build-pattern-start', patternlab);
444-
patternlab.graph = PatternGraph.loadFromFile(patternlab);
462+
463+
let graph = patternlab.graph = loadPatternGraph(deletePatternDir);
464+
465+
let graphNeedsUpgrade = !PatternGraph.checkVersion(graph);
466+
467+
if (graphNeedsUpgrade) {
468+
plutils.log.info("Due to an upgrade, a complete rebuild is required and the public/patterns directory was deleted. " +
469+
"Incremental build is available again on the next successful run.");
470+
471+
// Ensure that the freshly built graph has the latest version again.
472+
patternlab.graph.upgradeVersion();
473+
}
474+
475+
// Flags
476+
let incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade);
477+
478+
if (incrementalBuildsEnabled) {
479+
plutils.log.info("Incremental builds enabled.");
480+
} else {
481+
// needs to be done BEFORE processing patterns
482+
fs.removeSync(paths.public.patterns);
483+
fs.emptyDirSync(paths.public.patterns);
484+
}
445485

446486
try {
447487
patternlab.data = buildPatternData(paths.source.data, fs);
@@ -511,34 +551,32 @@ var patternlab_engine = function (config) {
511551
cacheBuster: patternlab.cacheBuster
512552
});
513553

514-
let patternsToBuild = patternlab.patterns;
515-
516-
let graphNeedsUpgrade = !PatternGraph.checkVersion(patternlab.graph);
554+
// If deletePatternDir == true or graph needs to be updated
555+
// rebuild all patterns
556+
let patternsToBuild = null;
517557

518-
// Incremental builds are enabled, but we cannot use them
519-
if (!deletePatternDir && graphNeedsUpgrade) {
520-
plutils.log.info("Due to an upgrade, a complete rebuild is required. " +
521-
"Incremental build is available again on the next run.");
522-
523-
// Ensure that the freshly built graph has the latest version again.
524-
patternlab.graph.upgradeVersion();
525-
}
558+
if (incrementalBuildsEnabled) {
559+
// When the graph was loaded from file, some patterns might have been moved/deleted between runs
560+
// so the graph data become out of sync
561+
patternlab.graph.sync().forEach(n => {
562+
plutils.log.info("[Deleted/Moved] " + n);
563+
});
526564

527-
//delete the contents of config.patterns.public before writing
528-
//Also if the serialized graph must be updated
529-
if (deletePatternDir || graphNeedsUpgrade) {
530-
fs.removeSync(paths.public.patterns);
531-
fs.emptyDirSync(paths.public.patterns);
532-
} else {
533565
// TODO Find created or deleted files
534566
let now = new Date().getTime();
535-
var modified = pattern_assembler.find_modified_patterns(now, patternlab);
567+
let modified = pattern_assembler.find_modified_patterns(now, patternlab);
536568

537569
// First mark all modified files
538570
for (let p of modified) {
539571
p.compileState = CompileState.NEEDS_REBUILD;
540572
}
541573
patternsToBuild = patternlab.graph.compileOrder();
574+
} else {
575+
// build all patterns, mark all to be rebuilt
576+
patternsToBuild = patternlab.patterns;
577+
for (let p of patternsToBuild) {
578+
p.compileState = CompileState.NEEDS_REBUILD;
579+
}
542580
}
543581

544582

core/lib/ui_builder.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ var ui_builder = function () {
568568
output += 'var ishControls = {"ishControlsHide":' + JSON.stringify(patternlab.config.ishControlsHide) + '};' + eol;
569569

570570
//navItems
571-
output += 'var navItems = {"patternTypes": ' + JSON.stringify(patternlab.patternTypes) + ', "ishControlsHide": ' + JSON.stringify(patternlab.config.ishControlsHide) +'};' + eol;
571+
output += 'var navItems = {"patternTypes": ' + JSON.stringify(patternlab.patternTypes) + ', "ishControlsHide": ' + JSON.stringify(patternlab.config.ishControlsHide) + '};' + eol;
572572

573573
//patternPaths
574574
output += 'var patternPaths = ' + JSON.stringify(patternlab.patternPaths) + ';' + eol;

0 commit comments

Comments
 (0)