Skip to content

Commit

Permalink
Revised "overlooked asset" detection; tesselinclude hinting. Fixes gh…
Browse files Browse the repository at this point in the history
…-644 (#655)

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
  • Loading branch information
rwaldron committed Apr 11, 2016
1 parent fc24618 commit 8d9d3ee
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 55 deletions.
23 changes: 21 additions & 2 deletions bin/tessel-2.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,16 @@ makeCommand('run')
default: false,
help: 'Deploy all files in project including those not used by the program, excluding any files matched by non-negated rules in .tesselignore and including any files matched by rules in .tesselinclude. Program is run from specified "entryPoint" file.'
})
.help('Deploy a script to Tessel and run it with Node');
.help(`
Deploy a script to Tessel and run it with Node.
Assets that are not directly deployed as a dependency via require analysis,
for example images or html files of an application (and their directories),
must be listed in a .tesselinclude in the root of your project.
This can be created manually or by typing 't2 init'.
For more information, visit: https://tessel.io/docs/cli#starting-projects
`);

makeCommand('push')
.callback(function(opts) {
Expand Down Expand Up @@ -175,7 +184,17 @@ makeCommand('push')
default: false,
help: 'Push all files in project including those not used by the program, excluding any files matched by non-negated rules in .tesselignore and including any files matched by rules in .tesselinclude. Program is run from specified "entryPoint" file.'
})
.help('Pushes the file/dir to Flash memory to be run anytime the Tessel is powered, runs the file immediately once the file is copied over');
.help(`
Pushes the file/dir to Flash memory to be run anytime the Tessel is powered,
runs the file immediately once the file is copied over.
Assets that are not directly deployed as a dependency via require analysis,
for example images or html files of an application (and their directories),
must be listed in a .tesselinclude in the root of your project.
This can be created manually or by typing 't2 init'.
For more information, visit: https://tessel.io/docs/cli#starting-projects
`);

makeCommand('erase')
.callback(callControllerCallback('eraseScript'))
Expand Down
41 changes: 22 additions & 19 deletions lib/tessel/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -768,28 +768,15 @@ actions.tarBundle = function(opts) {
// with the files, but without directly tampering with the
// project files themselves.
var tempBundleDir = fsTemp.mkdirSync();
var common = ['node_modules', 'package.json', opts.resolvedEntryPoint];
var assets = fs.readdirSync(target).filter(entry => (common.indexOf(entry) === -1));

if (assets.length) {
logs.warn(
tags.stripIndent `
The following items were found in your project directory, but not deployed.
${assets.join('\n')}
If you need to deploy them to your Tessel 2, you must have a .tesselinclude
file that lists the file and directory assets for your application. This can be
created manually or by typing 't2 init'.
For more information, visit: https://tessel.io/docs/cli#starting-projects
`
);
}

if (opts.slim) {
return new Promise((resolve, reject) => {
// Resolve .tesselignore
// Setup for detecting "overlooked" assets (files, directories, etc.)
var common = ['node_modules', 'package.json', '.tesselinclude', opts.resolvedEntryPoint];
// These will be compared against the dependency graph
var assets = fs.readdirSync(globRoot)
.filter(entry => (common.indexOf(entry) === -1))
.map(entry => path.join(globRoot, entry));

// Initialize a project for dependency graphing
var entry = path.join(relative, opts.resolvedEntryPoint);
Expand Down Expand Up @@ -837,6 +824,18 @@ actions.tarBundle = function(opts) {
}
}

if (assets.length) {
assets = assets.filter(asset => {
// If the asset was included in the dependency graph, then it can
// be removed from the potentially overlooked assets.
if ((dependency.file === asset || dependency.file.includes(asset)) ||
path.dirname(dependency.file) === path.dirname(asset)) {
return false;
}
return true;
});
}

fs.outputFileSync(target, source);

written[target] = true;
Expand All @@ -852,6 +851,10 @@ actions.tarBundle = function(opts) {
});
}

if (assets.length) {
logs.warn('Some assets in this project were not deployed (see: t2 run --help)');
}

actions.injectBinaryModules(globRoot, tempBundleDir, opts)
.then(() => {
var fstream = new Reader({
Expand Down
75 changes: 44 additions & 31 deletions test/unit/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1592,8 +1592,8 @@ exports['deploy.tarBundle'] = {
});
},

bothDetectAssetsWithoutInclude: function(test) {
test.expect(10);
detectAssetsWithoutInclude: function(test) {
test.expect(4);

var entryPoint = 'index.js';
var target = 'test/unit/fixtures/project-assets-without-include';
Expand All @@ -1615,41 +1615,54 @@ exports['deploy.tarBundle'] = {
*/


Promise.all([
deploy.tarBundle({
target: path.normalize(target),
resolvedEntryPoint: entryPoint,
slim: true,
}),
deploy.tarBundle({
target: path.normalize(target),
resolvedEntryPoint: entryPoint,
}),
]).then(() => {

test.equal(this.readdirSync.callCount, 2);
test.equal(this.readdirSync.firstCall.args[0], target);
deploy.tarBundle({
target: path.normalize(target),
resolvedEntryPoint: entryPoint,
slim: true,
}).then(() => {

test.equal(this.readdirSync.callCount, 1);
test.equal(this.readdirSync.lastCall.args[0], target);

// In both cases, logs.warn should've been called with the
// warning message and a list of the present, but unnaccounted for
// asset files and directories.
test.equal(this.logsWarn.callCount, 1);
test.equal(this.logsWarn.firstCall.args[0], 'Some assets in this project were not deployed (see: t2 run --help)');

test.equal(this.logsWarn.callCount, 2);
test.done();
});
},

[
'mock-foo.js',
'nested',
'other.js',
].forEach(asset => {
test.equal(this.logsWarn.firstCall.args[0].includes(asset), true);
test.equal(this.logsWarn.lastCall.args[0].includes(asset), true);
});
detectAssetsWithoutIncludeEliminatedByDepGraph: function(test) {
test.expect(3);

this.logsWarn.firstCall.args[0].includes('The following items were found in your project directory, but not deployed.');
this.logsWarn.firstCall.args[0].includes('If you need to deploy them to your Tessel 2, you must have a .tesselinclude\n file that lists the file and directory assets for your application. This can be\n created manually or by typing \'t2 init\'.');
this.logsWarn.firstCall.args[0].includes('For more information, visit: https://tessel.io/docs/cli#starting-projects');
var entryPoint = 'index.js';
var target = 'test/unit/fixtures/project-assets-without-include-eliminated-by-dep-graph';

/*
project-assets-without-include
├── index.js
├── mock-foo.js
├── nested
│   └── another.js
├── node_modules
│   └── foo
│   ├── index.js
│   └── package.json
└── package.json
3 directories, 6 files
*/

deploy.tarBundle({
target: path.normalize(target),
resolvedEntryPoint: entryPoint,
slim: true,
}).then(() => {
test.equal(this.readdirSync.callCount, 1);
test.equal(this.readdirSync.lastCall.args[0], target);
test.equal(this.logsWarn.callCount, 0);

// Ultimately, all assets were accounted for, even though
// no tesselinclude existed.
test.done();
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var path = require('path');
var fs = require('fs');
var foo = require('./mock-foo');
var nested = require('./nested/another');

console.log(foo());
console.log(nested);

fs.readFile(path.normalize('node_modules/foo/package.json'), 'utf8', function(error, contents) {
if (error) {
process.exit(1);
}
console.log(contents);
process.exit(0);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function() {
return 'I was included';
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('testing deploy');

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

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "project-assets-without-include-eliminated-by-dep-graph",
"version": "0.0.1",
"description": "project-assets-without-include-eliminated-by-dep-graph",
"main": "index.js"
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = function() {
return '!!mock foo!! <-- this string must not appear in bundle.js';
return 'I was included';
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "project-include-without-ignore",
"name": "project-assets-without-include",
"version": "0.0.1",
"description": "project-include-without-ignore",
"description": "project-assets-without-include",
"main": "index.js"
}

0 comments on commit 8d9d3ee

Please sign in to comment.