Compare commits
111 commits
update_set
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf90ab1c24 | ||
|
|
e66281996c | ||
|
|
71486a5054 | ||
|
|
4ba021507d | ||
|
|
192181b444 | ||
|
|
6eae151e02 | ||
|
|
0e8927ed1e | ||
|
|
4f926f571f | ||
|
|
0d5f143068 | ||
|
|
023b56b877 | ||
|
|
ef2fe8f080 | ||
|
|
4bf4796dda | ||
|
|
a45801528f | ||
|
|
bca81a3e59 | ||
|
|
cdee44ff92 | ||
|
|
4270790990 | ||
|
|
ab243a1946 | ||
|
|
f12471a144 | ||
|
|
72e39a0d61 | ||
|
|
e162c195e4 | ||
|
|
3f5a9daf1b | ||
|
|
275d391afe | ||
|
|
2b5dee5081 | ||
|
|
115c14fafb | ||
|
|
63647ff448 | ||
|
|
88477512cd | ||
|
|
ffac7e840c | ||
|
|
67e2f66d0b | ||
|
|
0aac8897f3 | ||
|
|
5c21a9d827 | ||
|
|
1c2097e76b | ||
|
|
0b34446083 | ||
|
|
14c2bd5578 | ||
|
|
de6fafa9ef | ||
|
|
71d095fbb9 | ||
|
|
eab1701259 | ||
|
|
17f123d461 | ||
|
|
a0fb85863c | ||
|
|
c750e7a3c6 | ||
|
|
1c8d83fc4d | ||
|
|
a5f15dd1c5 | ||
|
|
bb66c5fb87 | ||
|
|
8ed034c50c | ||
|
|
739cdad201 | ||
|
|
2a002742c9 | ||
|
|
34f35bc029 | ||
|
|
866cbb0b07 | ||
|
|
c9bee8c65a | ||
|
|
21a71ba103 | ||
|
|
97f3c5a523 | ||
|
|
f133dec99d | ||
|
|
5d2a693929 | ||
|
|
253e929717 | ||
|
|
7339e6caf9 | ||
|
|
ceca5008b2 | ||
|
|
b2b73e8556 | ||
|
|
008e44acaf | ||
|
|
6ae9e9bfc9 | ||
|
|
33be18de0d | ||
|
|
4cdbba68a8 | ||
|
|
a3f1c33eb2 | ||
|
|
2b2f45ea7d | ||
|
|
65efc495d9 | ||
|
|
4377e56e38 | ||
|
|
e68c3e6fad | ||
|
|
529d489b4f | ||
|
|
5291fa0b85 | ||
|
|
72f244304d | ||
|
|
7d906207a2 | ||
|
|
cd79c179cf | ||
|
|
47a7045e07 | ||
|
|
67e3aa4c85 | ||
|
|
beea098827 | ||
|
|
dc05c93b35 | ||
|
|
e542ed3f96 | ||
|
|
865d960e12 | ||
|
|
26e4c37b3e | ||
|
|
b965c171ba | ||
|
|
4b00a4671b | ||
|
|
e0d4bf0847 | ||
|
|
6a951bbd0e | ||
|
|
979e37c4c8 | ||
|
|
1502067f78 | ||
|
|
845d26a341 | ||
|
|
427536debb | ||
|
|
524b3b8401 | ||
|
|
8b324b62d4 | ||
|
|
ff39d5f5cb | ||
|
|
bee24d02be | ||
|
|
f229fcac1c | ||
|
|
ac35b34f35 | ||
|
|
94a9bee913 | ||
|
|
02c238b2b7 | ||
|
|
53084e290b | ||
|
|
f946db7e93 | ||
|
|
e9f9d4d88a | ||
|
|
d0accd7a86 | ||
|
|
935d333a7c | ||
|
|
31f1545311 | ||
|
|
9b2a272189 | ||
|
|
cbab5fdd15 | ||
|
|
62b453334f | ||
|
|
992983838b | ||
|
|
4d61650ef2 | ||
|
|
9aaa89ebb0 | ||
|
|
1d6aab4e8f | ||
|
|
78f052678c | ||
|
|
8eb4205245 | ||
|
|
b238f6e53a | ||
|
|
bc2caa435c | ||
|
|
ac39a871fb |
56 changed files with 4981 additions and 1840 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
node_modules
|
||||
repositories
|
||||
users.db
|
||||
database/webide_data_store
|
||||
|
||||
/editor.tar.gz
|
||||
__MACOSX
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
- 0.6
|
||||
- 4.8.2
|
||||
|
|
|
|||
95
README.md
95
README.md
|
|
@ -2,76 +2,50 @@ Adafruit webIDE
|
|||
================
|
||||
This is a simple editor designed to help learn the Raspberry Pi and Beaglebone components, and more. This editor is designed solely for use on your secure private network as of now.
|
||||
|
||||
## Note
|
||||
This guidance and repo are deprecated and no longer supported.
|
||||
It is here for historical purposes only
|
||||
******************************************************************************
|
||||
|
||||
Debian Installation (Raspberry Pi and BeagleBone Black)
|
||||
============
|
||||
|
||||
The WebIDE installer is currently targeting Debian Stretch (latest Raspbian) installations only.
|
||||
|
||||
On the Raspberry PI or BeagleBone Black (after expanding the file system):
|
||||
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/scripts/install.sh | sudo sh
|
||||
|
||||
Alternatively, you can install using the .deb file:
|
||||
|
||||
curl -O http://adafruit-download.s3.amazonaws.com/adafruitwebide-0.3.8-Linux.deb
|
||||
sudo dpkg -i adafruitwebide-0.3.8-Linux.deb
|
||||
curl -O https://adafruit-download.s3.amazonaws.com/adafruitwebide-0.3.12-Linux.deb
|
||||
sudo dpkg -i adafruitwebide-0.3.12-Linux.deb
|
||||
sudo apt-get -f install
|
||||
|
||||
Note: As part of the installation process, the 'webide' user is given access to sudo and sudoers,
|
||||
Note: As part of the installation process, the 'webide' user is given access to sudo and sudoers,
|
||||
similar to the 'pi' user. This is needed in order to easily access GPIO pins from the Editor.
|
||||
If you don't need these features, feel free to manually install the editor below.
|
||||
|
||||
Note: This is also the default installation for any Debian or Ubuntu operating systems
|
||||
|
||||
Angstrom Installation (BeagleBone Black)
|
||||
Manual Installation
|
||||
============
|
||||
|
||||
On the Beaglebone (as the default root user), execute each line independently:
|
||||
|
||||
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
|
||||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install-angstrom.sh | sh
|
||||
|
||||
Note: The curl -k command is used due to the Beaglebone not having the github SSL certificate in the default installation.
|
||||
|
||||
Note: If you've replaced the default operating system (Angstrom) with Debian or Ubuntu, use the Raspberry Pi installation instructions.
|
||||
|
||||
Manual Installation (without process monitor)
|
||||
============
|
||||
|
||||
On the Raspberry PI:
|
||||
|
||||
sudo apt-get update && sudo apt-get -y install build-essential nodejs nodejs-legacy npm redis-server git
|
||||
git clone git://github.com/adafruit/Adafruit-WebIDE.git
|
||||
cd Adafruit-WebIDE
|
||||
mkdir tmp
|
||||
npm config set tmp tmp
|
||||
npm install
|
||||
editor config/config.js (change port 80 to your port of choice)
|
||||
nodejs server.js
|
||||
|
||||
You can look at the install.sh script if you'd like a process monitor, and to install it
|
||||
as a daemon.
|
||||
Follow along in the [installation script][1] and pick and choose
|
||||
the components you'd like to install.
|
||||
|
||||
Uninstallation
|
||||
============
|
||||
|
||||
Debian (Raspberry PI and BeagleBone Black):
|
||||
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall.sh | sudo sh
|
||||
|
||||
Or if you installed with the .deb file:
|
||||
|
||||
sudo apt-get remove adafruitwebide
|
||||
|
||||
Angstrom (BeagleBone Black, as default root user):
|
||||
|
||||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall-angstrom.sh | sh
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/scripts/uninstall.sh | sudo sh
|
||||
|
||||
Manual Uninstallation
|
||||
============
|
||||
|
||||
On the Raspberry PI or BeagleBone Black:
|
||||
|
||||
rm -r Adafruit-WebIDE
|
||||
rm ~/.ssh/id_rsa_bitbucket*
|
||||
Follow along in the [uninstallation script][2] and pick and choose
|
||||
the components you'd like to remove.
|
||||
|
||||
Running the Editor
|
||||
============
|
||||
|
|
@ -80,7 +54,7 @@ Using Firefox or Chrome (and likely any other webkit browser) on any computer in
|
|||
|
||||
Raspberry Pi:
|
||||
|
||||
http://raspberrypi.local
|
||||
http://raspberrypi.local:8080
|
||||
|
||||
BeagleBone:
|
||||
|
||||
|
|
@ -90,36 +64,18 @@ Restart the Editor
|
|||
============
|
||||
|
||||
If for any reason you need to restart the editor, you can execute the following commands in order
|
||||
|
||||
sudo service adafruit-webide.sh stop
|
||||
sudo service adafruit-webide.sh start
|
||||
|
||||
sudo systemctl restart adafruit-webide
|
||||
sudo systemctl start adafruit-webide
|
||||
|
||||
Sudo is required to restart due to the editor running as the 'webide' user.
|
||||
|
||||
Advanced Options
|
||||
Status or Logs for the Editor
|
||||
============
|
||||
|
||||
Offline Mode Installation:
|
||||
sudo systemctl status adafruit-webide
|
||||
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh -s - --offline
|
||||
|
||||
Note: Offline mode does not setup git in any way other than installing it. You'll want to git config your
|
||||
email and name, and setup your ssh keys.
|
||||
|
||||
GitHub Mode Installation:
|
||||
|
||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh -s - --github
|
||||
|
||||
Note: GitHub mode does not automatically create, and post an ssh key to your GitHub account. It requires
|
||||
a bit more manual setup at this time.
|
||||
|
||||
Enable support for Makefiles (execute on the Pi in the terminal, post-installation):
|
||||
|
||||
redis-cli hmset editor:settings enable_make "on"
|
||||
|
||||
Disable:
|
||||
|
||||
redis-cli hmset editor:settings enable_make "off"
|
||||
Logs are in syslog: /var/log/syslog
|
||||
|
||||
License
|
||||
============
|
||||
|
|
@ -130,3 +86,6 @@ http://www.gnu.org/licenses/agpl-3.0.html
|
|||
SCREENSHOTS
|
||||
===========
|
||||

|
||||
|
||||
[1]: https://github.com/adafruit/Adafruit-WebIDE/blob/master/scripts/install.sh
|
||||
[2]: https://github.com/adafruit/Adafruit-WebIDE/blob/master/scripts/uninstall.sh
|
||||
|
|
|
|||
BIN
bin/node_hf/node
BIN
bin/node_hf/node
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
node hardfloat v0.8.16
|
||||
BIN
bin/node_sf/node
BIN
bin/node_sf/node
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
node softfloat v0.8.9
|
||||
|
|
@ -2,19 +2,16 @@ Welcome to the Adafruit webIDE.
|
|||
|
||||
We've pre-loaded the Adafruit Python libraries that you may find useful.
|
||||
|
||||
By navigating into those libraries, you can choose to copy them into your
|
||||
project folder, so you can edit, and save them. If you ever need to start
|
||||
over, just delete your copied project folder, and grab the
|
||||
By navigating into those libraries, you can choose to copy them into your
|
||||
project folder, so you can edit, and save them. If you ever need to start
|
||||
over, just delete your copied project folder, and grab the
|
||||
Adafruit libraries again.
|
||||
|
||||
We've also created a folder you can start putting your projects into. This
|
||||
is a version-controlled repository stored in your Bitbucket account.
|
||||
Whenever you create projects and files within this folder, they will be
|
||||
versioned and saved at Bitbucket.
|
||||
We've also created a folder you can start putting your projects into.
|
||||
|
||||
This file was pre-loaded in your projects folder, and is located in the
|
||||
This file was pre-loaded in your projects folder, and is located in the
|
||||
'my-pi-projects' link to the left.
|
||||
|
||||
We have usage information, installation instructions and various
|
||||
other information you may find useful at the Adafruit Learning System:
|
||||
other information you may find useful at the Adafruit Learning System:
|
||||
http://learn.adafruit.com/webide
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@
|
|||
//Change offline in /config.
|
||||
//Change github in /config.
|
||||
exports.editor = {
|
||||
"port": 80,
|
||||
"version": "0.3.8",
|
||||
"version_url": "https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/version.txt",
|
||||
"offline": false,
|
||||
"github": false
|
||||
"port": 3000,
|
||||
"version": "0.8.0",
|
||||
"version_url": "https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/release/version.txt"
|
||||
};
|
||||
|
||||
exports.adafruit = {
|
||||
|
|
@ -53,4 +51,4 @@ exports.term = {
|
|||
"#eeeeec"
|
||||
]
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,30 +1,148 @@
|
|||
var fs_helper = require('../helpers/fs_helper'),
|
||||
winston = require('winston'),
|
||||
editor_setup = require('../helpers/editor_setup'),
|
||||
path = require('path'),
|
||||
redis = require('redis'),
|
||||
client = redis.createClient(),
|
||||
git_helper = require('../helpers/git_helper'),
|
||||
updater = require('../helpers/updater'),
|
||||
scheduler = require('../helpers/scheduler'),
|
||||
debug_helper = require('../helpers/python/debug_helper'),
|
||||
exec_helper = require('../helpers/exec_helper'),
|
||||
scheduler = require('../helpers/scheduler'),
|
||||
config = require('../config/config'),
|
||||
check = require('validator').check,
|
||||
sanitize = require('validator').sanitize;
|
||||
db = require('../models/webideModel'),
|
||||
sanitize = require('validator');
|
||||
|
||||
var REPOSITORY_PATH = path.resolve(__dirname, "../repositories");
|
||||
|
||||
//Loads the editor
|
||||
exports.index = function(req, res) {
|
||||
var shown_notification = false;
|
||||
client.get('editor:shown_notification', function(err, result) {
|
||||
if (result) {
|
||||
shown_notification = result;
|
||||
req.session.message = undefined;
|
||||
db.findOne({"type": "user"}, function(err, user) {
|
||||
if (!user) {
|
||||
req.session.message = "Set your name and email prior to continuing to the editor.";
|
||||
res.redirect('/setup');
|
||||
} else {
|
||||
client.set('editor:shown_notification', true);
|
||||
res.render('editor/index', {profile: req.user, version: config.editor.version, shown_notification: false});
|
||||
}
|
||||
res.render('editor/index', {profile: req.user, version: config.editor.version, shown_notification: shown_notification});
|
||||
});
|
||||
};
|
||||
|
||||
exports.create_repository = function(req, res) {
|
||||
var repository_url = sanitize(req.body.repository_url).xss().trim();
|
||||
var retain_remote = sanitize(req.body.retain_remote).xss().trim();
|
||||
exports.editor = function(ws, req) {
|
||||
config.editor_ws = ws;
|
||||
winston.debug('socket io connection completed');
|
||||
|
||||
git_helper.clone_update_remote_push(req.user, repository_url, retain_remote, function(err, status) {
|
||||
function send_message(type, data) {
|
||||
ws.send(JSON.stringify({type: type, data: data}));
|
||||
}
|
||||
|
||||
//emit on first connection
|
||||
send_message('cwd-init', {dirname: REPOSITORY_PATH});
|
||||
scheduler.emit_scheduled_jobs(ws);
|
||||
|
||||
ws.on('message', function(msg) {
|
||||
var message = JSON.parse(msg);
|
||||
var type = message.type;
|
||||
var data = message.data;
|
||||
|
||||
winston.debug("Editor action type: " + type);
|
||||
|
||||
switch (type) {
|
||||
case 'self-check-request':
|
||||
winston.debug('self-check-request');
|
||||
editor_setup.health_check(ws);
|
||||
break;
|
||||
case 'git-delete':
|
||||
git_helper.remove_commit_push(data.file, function(err, status) {
|
||||
send_message('git-delete-complete', {err: err, status: status});
|
||||
});
|
||||
break;
|
||||
case 'git-pull':
|
||||
var name = data.file ? data.file.name : "";
|
||||
git_helper.pull(name, "origin", "master", function(err, status) {
|
||||
send_message('git-pull-complete', {err: err, status: status});
|
||||
});
|
||||
break;
|
||||
case 'git-is-modified':
|
||||
git_helper.is_modified(data.file, function(err, status) {
|
||||
send_message('git-is-modified-complete', {is_modified: status});
|
||||
});
|
||||
break;
|
||||
case 'commit-file':
|
||||
var commit_message = "";
|
||||
|
||||
if (data.message) {
|
||||
commit_message = data.message;
|
||||
} else {
|
||||
commit_message = "Modified " + data.file.name;
|
||||
}
|
||||
|
||||
git_helper.commit_push_and_save(data.file, commit_message, function(err, status) {
|
||||
send_message('commit-file-complete', {err: err, status: status});
|
||||
});
|
||||
break;
|
||||
case 'move-file':
|
||||
git_helper.move_commit_push(data.file, function(err) {
|
||||
console.log('move-file', err);
|
||||
send_message('move-file-complete', {err: err});
|
||||
});
|
||||
break;
|
||||
case 'editor-check-updates':
|
||||
// TODO: Explore adding auto-updater again
|
||||
// updater.check_for_updates(ws);
|
||||
break;
|
||||
case 'editor-update':
|
||||
updater.update(ws);
|
||||
break;
|
||||
case 'trace-file':
|
||||
exec_helper.trace_program(data.file, ws);
|
||||
break;
|
||||
case 'debug-command':
|
||||
debug_helper.debug_command(data, ws);
|
||||
break;
|
||||
case 'debug-file':
|
||||
debug_helper.start_debug(data.file, ws);
|
||||
break;
|
||||
case 'commit-run-file':
|
||||
exec_helper.execute_program(data.file, false);
|
||||
git_helper.commit_push_and_save(data.file, "Modified " + data.file.name, function(err, status) {
|
||||
send_message('commit-file-complete', {message: "Save was successful"});
|
||||
});
|
||||
break;
|
||||
case 'stop-script-execution':
|
||||
exec_helper.stop_program(data.file, false);
|
||||
break;
|
||||
case 'submit-schedule':
|
||||
scheduler.add_schedule(data, ws);
|
||||
break;
|
||||
case 'schedule-delete-job':
|
||||
scheduler.delete_job(data, ws);
|
||||
break;
|
||||
case 'schedule-toggle-job':
|
||||
scheduler.toggle_job(data, ws);
|
||||
break;
|
||||
case 'set-settings':
|
||||
data["type"] = "editor:settings";
|
||||
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||
db.update({type: "editor:settings"}, Object.assign(settings || {}, data || {}), { upsert: true }, function(err) {
|
||||
data["type"] = "editor:settings";
|
||||
if (err) winston.error(err);
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('disconnect', function() {
|
||||
debug_helper.client_disconnect();
|
||||
debug_helper.kill_debug();
|
||||
});
|
||||
}
|
||||
|
||||
exports.create_repository = function(req, res) {
|
||||
var repository_url = sanitize.trim(req.body.repository_url);
|
||||
|
||||
git_helper.clone_update_remote_push(req.user, repository_url, function(err, status) {
|
||||
if (err) res.send(err, 404);
|
||||
else res.send(status, 200);
|
||||
});
|
||||
|
|
@ -32,7 +150,7 @@ exports.create_repository = function(req, res) {
|
|||
|
||||
//Opens an image clicked from the editor navigator
|
||||
exports.image = function(req, res) {
|
||||
var temp_path = sanitize(req.query.path).xss().trim().replace('/filesystem/', '/repositories/');
|
||||
var temp_path = sanitize(req.query.path).trim().replace('/filesystem/', '/repositories/');
|
||||
//strip basic attempted path traversals
|
||||
temp_path = temp_path.replace('..', '');
|
||||
|
||||
|
|
@ -43,13 +161,15 @@ exports.image = function(req, res) {
|
|||
};
|
||||
|
||||
exports.upload_file = function(req, res) {
|
||||
console.log(req.files.files[0]);
|
||||
console.log(req.file);
|
||||
console.log(req.file.originalname);
|
||||
console.log(req.file.path);
|
||||
|
||||
var temp_path = sanitize(req.files.files[0].path).xss().trim();
|
||||
var file_name = sanitize(req.files.files[0].name).xss().trim();
|
||||
var temp_path = sanitize.trim(req.file.path);
|
||||
var file_name = sanitize.trim(req.file.originalname);
|
||||
file_name = file_name.replace(" ", "_");
|
||||
var folder_path = sanitize(req.body.path).xss().trim().replace('filesystem', 'repositories');
|
||||
|
||||
var folder_path = sanitize.trim(req.body.path).replace('filesystem', 'repositories');
|
||||
|
||||
var new_path = __dirname + '/..' + folder_path + file_name;
|
||||
new_path = path.resolve(new_path);
|
||||
|
||||
|
|
@ -58,9 +178,9 @@ exports.upload_file = function(req, res) {
|
|||
res.send(false, 200);
|
||||
} else {
|
||||
var comment = "Uploaded new File.";
|
||||
git_helper.commit_push_and_save({path: folder_path + file_name}, comment, null, function(err, status) {
|
||||
git_helper.commit_push_and_save({path: folder_path + file_name}, comment, function(err, status) {
|
||||
res.send(true, 200);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
var request_helper = require('../helpers/request_helper');
|
||||
|
||||
exports.index = function(req, res){
|
||||
if (req.user) {
|
||||
res.redirect('/editor');
|
||||
}
|
||||
};
|
||||
res.redirect('/editor');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,68 +1,44 @@
|
|||
var redis = require("redis"),
|
||||
client = redis.createClient(),
|
||||
var path = require('path'),
|
||||
db = require('../models/webideModel'),
|
||||
scripts_helper = require('../helpers/scripts_helper'),
|
||||
config = require('../config/config'),
|
||||
check = require('validator').check,
|
||||
sanitize = require('validator').sanitize;
|
||||
sanitize = require('validator');
|
||||
|
||||
exports.login = function(req, res){
|
||||
res.render('users/login', { title: 'test', user: req.user, github: config.editor.github });
|
||||
};
|
||||
|
||||
exports.logout = function(req, res){
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
};
|
||||
|
||||
// Instructional page that displays the bitbucket setup steps,
|
||||
// and inputs for OAuth and Git config
|
||||
// Instructional page that displays the setup steps
|
||||
exports.setup = function(req, res) {
|
||||
var locals = {
|
||||
consumer_key: "",
|
||||
consumer_secret: "",
|
||||
name: "",
|
||||
email: "",
|
||||
hostname: "",
|
||||
github: config.editor.github
|
||||
hostname: ""
|
||||
};
|
||||
|
||||
res.render('users/setup', locals);
|
||||
};
|
||||
|
||||
// Saves the bitbucket and git config setup information in Redis,
|
||||
// Saves the git config setup information in nedb,
|
||||
// submitted as a post from /setup
|
||||
exports.submit_setup = function(req, res) {
|
||||
var key, secret, name, email, message;
|
||||
var name, email, message;
|
||||
req.session.message = undefined;
|
||||
|
||||
function common_setup(name, email) {
|
||||
client.hmset("user", "name", name, "email", email, function() {
|
||||
db.update({"type": "user"}, {"type": "user", "name": name, "email": email}, { upsert: true }, function() {
|
||||
req.session.message = "Settings Successfully Configured.";
|
||||
res.redirect('/login');
|
||||
res.redirect('/editor');
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
key = sanitize(req.body.key).xss().trim();
|
||||
secret = sanitize(req.body.secret).xss().trim();
|
||||
name = sanitize(req.body.name).xss().trim();
|
||||
email = sanitize(req.body.email).xss().trim();
|
||||
check(email).isEmail();
|
||||
name = sanitize.trim(req.body.name);
|
||||
email = sanitize.trim(req.body.email);
|
||||
sanitize.isEmail(email);
|
||||
} catch (e) {
|
||||
req.session.message = e.message;
|
||||
console.log(e.message);
|
||||
}
|
||||
|
||||
if (key && secret && name && email) {
|
||||
if (config.editor.github) {
|
||||
client.hmset("github_oauth", "consumer_key", key, "consumer_secret", secret, function() {
|
||||
common_setup(name, email);
|
||||
});
|
||||
} else {
|
||||
client.hmset("bitbucket_oauth", "consumer_key", key, "consumer_secret", secret, function() {
|
||||
common_setup(name, email);
|
||||
});
|
||||
}
|
||||
if (name && email) {
|
||||
common_setup(name, email);
|
||||
} else {
|
||||
if (!req.session.message) {
|
||||
req.session.message = "Please set all fields, at the bottom of this page, in order to continue.";
|
||||
|
|
@ -73,31 +49,31 @@ exports.submit_setup = function(req, res) {
|
|||
|
||||
|
||||
exports.config = function(req, res) {
|
||||
client.hgetall('server', function (err, server) {
|
||||
db.findOne({type: "server"}, function (err, server) {
|
||||
var locals = {
|
||||
hostname: "",
|
||||
wifi_ssid: "",
|
||||
wifi_password: "",
|
||||
port: (server ? (server.port || "") : "")
|
||||
};
|
||||
|
||||
|
||||
res.render('users/config', locals);
|
||||
});
|
||||
};
|
||||
|
||||
// Saves the bitbucket and git config setup information in Redis,
|
||||
// Saves the git config setup information in nedb,
|
||||
// submitted as a post from /setup
|
||||
|
||||
//TODO: Refactor this...it's out of control!
|
||||
exports.submit_config = function(req, res) {
|
||||
var key, secret, name, email, message;
|
||||
var name, email, message;
|
||||
req.session.message = undefined;
|
||||
|
||||
try {
|
||||
hostname = sanitize(req.body.hostname).xss().trim();
|
||||
wifi_ssid = sanitize(req.body.wifi_ssid).xss().trim();
|
||||
wifi_password = sanitize(req.body.wifi_password).xss().trim();
|
||||
port = sanitize(req.body.port).xss().trim();
|
||||
hostname = sanitize.trim(req.body.hostname);
|
||||
wifi_ssid = sanitize.trim(req.body.wifi_ssid);
|
||||
wifi_password = sanitize.trim(req.body.wifi_password);
|
||||
port = sanitize.trim(req.body.port);
|
||||
if (hostname) {
|
||||
check(hostname).len(3, 25);
|
||||
}
|
||||
|
|
@ -119,7 +95,8 @@ exports.submit_config = function(req, res) {
|
|||
});
|
||||
}
|
||||
if (port) {
|
||||
client.hmset("server", "port", port, function() {
|
||||
db.update({type: "server"}, { $set: {"port": port}}, {}, function() {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -141,4 +118,4 @@ exports.set_datetime = function(req, res) {
|
|||
scripts_helper.set_datetime(function() {
|
||||
res.redirect('/login');
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
4
db/.gitignore
vendored
Normal file
4
db/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
0
error.log
Normal file
0
error.log
Normal file
|
|
@ -1,140 +1,70 @@
|
|||
var exec = require('child_process').exec,
|
||||
fs = require ('fs'),
|
||||
path = require('path'),
|
||||
git_helper = require('./git_helper'),
|
||||
fs_helper = require('./fs_helper'),
|
||||
redis = require('redis'),
|
||||
client = redis.createClient(),
|
||||
request_helper = require('./request_helper'),
|
||||
config = require('../config/config');
|
||||
var path = require('path'),
|
||||
winston = require('winston'),
|
||||
db = require('../models/webideModel'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require ('fs'),
|
||||
git_helper = require('./git_helper.js'),
|
||||
fs_helper = require('./fs_helper'),
|
||||
ws_helper = require('./websocket_helper'),
|
||||
config = require('../config/config');
|
||||
|
||||
fs.exists || (fs.exists = path.exists);
|
||||
|
||||
exports.setup_github = function(socket) {
|
||||
git_helper.set_config(function() {
|
||||
this.setup_adafruit_libraries(socket);
|
||||
});
|
||||
};
|
||||
|
||||
exports.setup_adafruit_libraries = function(socket) {
|
||||
exports.setup_adafruit_libraries = function(ws) {
|
||||
git_helper.clone_adafruit_libraries(config.adafruit.repository, config.adafruit.remote, function(cloned_libraries) {
|
||||
socket.emit("self-check-message", "Cloning remote Adafruit repository");
|
||||
ws_helper.send_message(ws, "self-check-message", "Cloning remote Adafruit repository");
|
||||
//cloned_libraries is false if they already existed...if false, let's pull the latest version of the adafruit libraries
|
||||
if (!cloned_libraries) {
|
||||
git_helper.pull(config.adafruit.repository, "origin", "master", function() {
|
||||
socket.emit("self-check-message", "Adafruit repository updated");
|
||||
ws_helper.send_message(ws, "self-check-message", "Adafruit repository updated");
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.offline_health_check = function(socket) {
|
||||
client.hgetall('editor:settings', function(err, settings) {
|
||||
exports.health_check = function(ws) {
|
||||
//TODO redis to nedb
|
||||
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||
if (settings) {
|
||||
settings.offline = true;
|
||||
} else {
|
||||
settings = {offline: true};
|
||||
}
|
||||
winston.debug("getting settings", settings);
|
||||
ws_helper.send_message(ws, "self-check-settings", settings);
|
||||
})
|
||||
|
||||
if (settings) {
|
||||
settings.offline = true;
|
||||
} else {
|
||||
settings = {offline: true};
|
||||
}
|
||||
console.log("getting settings", settings);
|
||||
socket.emit("self-check-settings", settings);
|
||||
});
|
||||
|
||||
console.log('self-check-complete');
|
||||
socket.emit('self-check-complete');
|
||||
};
|
||||
|
||||
//TODO this is a terrible mess..clean this up, no reason to have these big blocks of callbacks...uffda.
|
||||
exports.health_check = function(socket, profile) {
|
||||
var that = this;
|
||||
console.log(config.editor.offline);
|
||||
|
||||
if (config.editor.github) {
|
||||
this.setup_github(socket);
|
||||
}
|
||||
|
||||
if (config.editor.offline || config.editor.github) {
|
||||
this.offline_health_check(socket);
|
||||
return;
|
||||
}
|
||||
|
||||
var project_repository = 'git@bitbucket.org:' + profile.username + '/my-pi-projects.git';
|
||||
console.log(project_repository);
|
||||
|
||||
client.hgetall('editor:settings', function(err, settings) {
|
||||
if (typeof settings === 'undefined' || !settings) {
|
||||
settings = {};
|
||||
}
|
||||
|
||||
console.log("getting settings", settings);
|
||||
socket.emit("self-check-settings", settings);
|
||||
});
|
||||
|
||||
//check if the adafruit libraries exist, if not, clone them.
|
||||
request_helper.post_ssh_key(profile, function(err, response) {
|
||||
that.setup_adafruit_libraries(socket);
|
||||
this.setup_adafruit_libraries(ws);
|
||||
|
||||
git_helper.set_config(function() {
|
||||
request_helper.list_repositories(profile, function(err, list) {
|
||||
var exists = list.some(function(repository) {
|
||||
return (repository.name.toLowerCase() === config.defaults.repository.toLowerCase());
|
||||
});
|
||||
var my_repository = "my-pi-projects";
|
||||
fs_helper.check_for_repository(my_repository, function(err, exists) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Validated my-pi-projects");
|
||||
winston.debug(exists);
|
||||
if (exists) {
|
||||
git_helper.pull(my_repository, "origin", "master", function(err, status) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Updated my-pi-projects");
|
||||
ws_helper.send_message(ws, 'self-check-complete');
|
||||
});
|
||||
} else {
|
||||
git_helper.create_local_repository(my_repository, function(err, response) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Cloned my-pi-projects on local system");
|
||||
fs_helper.create_project_gitignore(function(err, file) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Added .gitignore in my-pi-projects");
|
||||
fs_helper.create_project_readme(function(err, file) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Added README.md in my-pi-projects");
|
||||
winston.debug(file);
|
||||
if (err) winston.error(err);
|
||||
|
||||
if (!exists) {
|
||||
request_helper.create_repository(profile, config.defaults.repository, function(err, response) {
|
||||
socket.emit("self-check-message", "Created my-pi-projects in Bitbucket");
|
||||
|
||||
git_helper.clone_repository(project_repository, function(err, response) {
|
||||
socket.emit("self-check-message", "Cloned my-pi-projects on local system");
|
||||
fs_helper.create_project_gitignore(function(err, file) {
|
||||
socket.emit("self-check-message", "Added .gitignore in my-pi-projects");
|
||||
fs_helper.create_project_readme(function(err, file) {
|
||||
socket.emit("self-check-message", "Added README.md in my-pi-projects");
|
||||
if (err) console.log(err);
|
||||
console.log(file);
|
||||
|
||||
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", null, function(err, response) {
|
||||
socket.emit("self-check-message", "Pushed changes to my-pi-projects to Bitbucket");
|
||||
socket.emit('self-check-complete');
|
||||
});
|
||||
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", function(err, response) {
|
||||
ws_helper.send_message(ws, "self-check-message", "Pushed changes to my-pi-projects");
|
||||
ws_helper.send_message(ws, 'self-check-complete');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
//check if repository exists here
|
||||
var my_repository = "my-pi-projects";
|
||||
fs_helper.check_for_repository(my_repository, function(err, exists) {
|
||||
socket.emit("self-check-message", "Validated my-pi-projects");
|
||||
if (exists) {
|
||||
git_helper.pull(my_repository, "origin", "master", function(err, status) {
|
||||
socket.emit("self-check-message", "Updated my-pi-projects");
|
||||
socket.emit('self-check-complete');
|
||||
});
|
||||
} else {
|
||||
git_helper.clone_repository(project_repository, function(err, response) {
|
||||
socket.emit("self-check-message", "Cloned my-pi-projects on local system");
|
||||
fs_helper.create_project_gitignore(function(err, file) {
|
||||
socket.emit("self-check-message", "Added .gitignore in my-pi-projects");
|
||||
fs_helper.create_project_readme(function(err, file) {
|
||||
socket.emit("self-check-message", "Added README.md in my-pi-projects");
|
||||
console.log(file);
|
||||
if (err) console.log(err);
|
||||
|
||||
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", null, function(err, response) {
|
||||
socket.emit("self-check-message", "Pushed changes to my-pi-projects to Bitbucket");
|
||||
socket.emit('self-check-complete');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}); // end of list repositories
|
||||
}); //end of git set config
|
||||
}); //end of post ssh key
|
||||
|
||||
};
|
||||
winston.debug("after everything");
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
var spawn = require('child_process').spawn,
|
||||
ws_helper = require('./websocket_helper'),
|
||||
//pty = require('pty.js'),
|
||||
path = require('path'),
|
||||
ipython, spawn_list = [];
|
||||
|
|
@ -8,7 +9,7 @@ var spawn = require('child_process').spawn,
|
|||
};*/
|
||||
|
||||
exports.execute_program = function(file, is_job) {
|
||||
|
||||
|
||||
console.log(file);
|
||||
if (file.extension === 'py') {
|
||||
execute_program(file, "python", is_job);
|
||||
|
|
@ -31,7 +32,7 @@ exports.stop_program = function(file, is_job) {
|
|||
|
||||
exports.trace_program = function(file, socket) {
|
||||
var file_path = path.resolve(__dirname + "/../repositories/" + file.path.replace('/filesystem/', ''));
|
||||
console.log(file_path);
|
||||
console.log(file_path);
|
||||
if (file.extension === 'py') {
|
||||
execute_python_trace(file_path, socket);
|
||||
} else if (file.extension === 'rb') {
|
||||
|
|
@ -54,12 +55,12 @@ function execute_python_trace(file_path, socket) {
|
|||
});
|
||||
|
||||
prog.stderr.on('data', function(data) {
|
||||
socket.emit('trace-program-stderr', {output: data.toString()});
|
||||
ws_helper.send_message(socket, 'trace-program-stderr', {output: data.toString()});
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
prog.on('exit', function(code) {
|
||||
socket.emit('trace-program-exit', {output: program_output});
|
||||
ws_helper.send_message(socket, 'trace-program-exit', {output: program_output});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -68,16 +69,16 @@ function execute_python_trace(file_path, socket) {
|
|||
ipython.removeAllListeners('data');
|
||||
require('../server').get_socket(file.username, function(socket) {
|
||||
if (is_job) {
|
||||
socket.emit('scheduler-start', {file: file});
|
||||
ws_helper.send_message(socket, 'scheduler-start', {file: file});
|
||||
}
|
||||
ipython.on('data', function(data) {
|
||||
console.log(data);
|
||||
//data = data.replace(/\[0;.*?In\s\[.*?\[0m/, '~-prompt-~');
|
||||
//data = data.replace(/In\s\[.*?\]:/, '~-prompt-~');
|
||||
if (is_job) {
|
||||
socket.emit('scheduler-executing', {file: file});
|
||||
ws_helper.send_message(socket, 'scheduler-executing', {file: file});
|
||||
} else {
|
||||
socket.emit('program-stdout', {output: data});
|
||||
ws_helper.send_message(socket, 'program-stdout', {output: data});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -104,41 +105,39 @@ function execute_program(file, type, is_job) {
|
|||
console.log('execute_program');
|
||||
console.log(file_path);
|
||||
|
||||
require('../server').get_socket(file.username, function(socket) {
|
||||
console.log(file);
|
||||
var cwd = get_cwd(file_path);
|
||||
var prog = spawn("sudo", [type, file_path], {cwd: cwd});
|
||||
var key = get_key(file);
|
||||
spawn_list.push({key: key, prog: prog});
|
||||
if (socket) {
|
||||
console.log('found socket, executing');
|
||||
handle_output(prog, file, is_job, socket);
|
||||
}
|
||||
});
|
||||
console.log(file);
|
||||
var cwd = get_cwd(file_path);
|
||||
var prog = spawn("sudo", [type, file_path], {cwd: cwd});
|
||||
var key = get_key(file);
|
||||
spawn_list.push({key: key, prog: prog});
|
||||
if (socket) {
|
||||
console.log('found socket, executing');
|
||||
handle_output(prog, file, is_job, socket);
|
||||
}
|
||||
}
|
||||
|
||||
function handle_output(prog, file, is_job, socket) {
|
||||
if (is_job) {
|
||||
socket.emit('scheduler-start', {file: file});
|
||||
ws_helper.send_message(socket, 'scheduler-start', {file: file});
|
||||
}
|
||||
|
||||
prog.stdout.on('data', function(data) {
|
||||
if (is_job) {
|
||||
console.log(data.toString());
|
||||
socket.emit('scheduler-executing', {file: file});
|
||||
ws_helper.send_message(socket, 'scheduler-executing', {file: file});
|
||||
} else {
|
||||
console.log(data.toString());
|
||||
socket.emit('program-stdout', {output: data.toString()});
|
||||
ws_helper.send_message(socket, 'program-stdout', {output: data.toString()});
|
||||
}
|
||||
});
|
||||
|
||||
prog.stderr.on('data', function(data) {
|
||||
if (is_job) {
|
||||
console.log(data.toString());
|
||||
socket.emit('scheduler-error', {file: file, error: data});
|
||||
ws_helper.send_message(socket, 'scheduler-error', {file: file, error: data});
|
||||
} else {
|
||||
console.log(data.toString());
|
||||
socket.emit('program-stderr', {output: data.toString()});
|
||||
ws_helper.send_message(socket, 'program-stderr', {output: data.toString()});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -151,10 +150,10 @@ function handle_output(prog, file, is_job, socket) {
|
|||
}
|
||||
|
||||
if (is_job) {
|
||||
socket.emit('scheduler-exit', {code: code, file: file});
|
||||
ws_helper.send_message(socket, 'scheduler-exit', {code: code, file: file});
|
||||
} else {
|
||||
socket.emit('program-exit', {code: code});
|
||||
ws_helper.send_message(socket, 'program-exit', {code: code});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
util = require('util'),
|
||||
config = require('../config/config');
|
||||
config = require('../config/config'),
|
||||
winston = require('winston'),
|
||||
exec = require('child_process').exec;
|
||||
|
||||
/*
|
||||
* Checks to see if a bitbucket ssh key exists already.
|
||||
* Checks to see if an ssh key exists already.
|
||||
*/
|
||||
exports.has_ssh_key = function has_ssh_key(cb) {
|
||||
path.exists(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', function(exists) {
|
||||
exports.has_ssh_key = function has_ssh_key(key_name, cb) {
|
||||
fs.exists(path.resolve(process.env['HOME'], '/.ssh/', key_name), function(exists) {
|
||||
if (exists) {
|
||||
cb(true);
|
||||
} else {
|
||||
|
|
@ -18,15 +18,15 @@ exports.has_ssh_key = function has_ssh_key(cb) {
|
|||
};
|
||||
|
||||
/*
|
||||
* Generates an ssh key for Bitbucket
|
||||
* Generates an ssh key
|
||||
*/
|
||||
exports.generate_ssh_key = function(cb) {
|
||||
exports.generate_ssh_key = function(key_name, cb) {
|
||||
var self = this;
|
||||
self.has_ssh_key(function(exists) {
|
||||
self.has_ssh_key(key_name, function(exists) {
|
||||
if (exists) {
|
||||
cb();
|
||||
} else {
|
||||
exec("ssh-keygen -b 2048 -N '' -f ~/.ssh/id_rsa_bitbucket -t rsa -q", function(err, stdout, stderr) {
|
||||
exec("ssh-keygen -b 2048 -N '' -f ~/.ssh/" + key_name + "-t rsa -q", function(err, stdout, stderr) {
|
||||
//console.log(err, stdout, stderr);
|
||||
self.append_to_ssh_config(function() {
|
||||
cb();
|
||||
|
|
@ -36,46 +36,17 @@ exports.generate_ssh_key = function(cb) {
|
|||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Append bitbucket.org to the ssh config file to disable StrictHostKeyChecking.
|
||||
* This isn't great, but we need a way for beginners to get past the known_host checks.
|
||||
*/
|
||||
exports.append_to_ssh_config = function append_to_ssh_config(cb) {
|
||||
var ssh_config_file = process.env['HOME'] + '/.ssh/config';
|
||||
var identity_info = "Host bitbucket.org \r\n\tHostName bitbucket.org\r\n\tStrictHostKeyChecking no\r\n\tPreferredAuthentications publickey\r\n\tIdentityFile ~/.ssh/id_rsa_bitbucket";
|
||||
|
||||
path.exists(ssh_config_file, function(exists) {
|
||||
if (exists) {
|
||||
//file exists, let's check if it has the bitbucket host in it, otherwise add it
|
||||
fs.readFile(ssh_config_file, 'ascii', function(err, data) {
|
||||
if (data.indexOf('bitbucket.org') !== -1) {
|
||||
cb();
|
||||
} else {
|
||||
var file = fs.createWriteStream(ssh_config_file, {'flags': 'a'});
|
||||
file.write(identity_info, function() {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fs.writeFile(ssh_config_file, identity_info, function(err) {
|
||||
if(err) console.log(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.read_or_generate_key = function(cb) {
|
||||
exports.read_or_generate_key = function(key_name, cb) {
|
||||
var self = this;
|
||||
self.has_ssh_key(function(has_key) {
|
||||
self.has_ssh_key(key_name, function(has_key) {
|
||||
if (has_key) {
|
||||
fs.readFile(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', 'ascii', function(err,data){
|
||||
fs.readFile(process.env['HOME'] + '/.ssh/' + key_name, 'ascii', function(err,data){
|
||||
cb(data);
|
||||
});
|
||||
} else {
|
||||
self.generate_ssh_key(function() {
|
||||
fs.readFile(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', 'ascii', function(err,data){
|
||||
self.generate_ssh_key(key_name, function() {
|
||||
fs.readFile(process.env['HOME'] + '/.ssh/' + key_name, 'ascii', function(err,data){
|
||||
cb(data);
|
||||
});
|
||||
});
|
||||
|
|
@ -109,9 +80,11 @@ exports.move_uploaded_file = function(temp_path, new_path, cb) {
|
|||
var is = fs.createReadStream(temp_path);
|
||||
var os = fs.createWriteStream(new_path);
|
||||
|
||||
util.pump(is, os, function() {
|
||||
fs.unlinkSync(temp_path);
|
||||
cb();
|
||||
is.pipe(os);
|
||||
|
||||
is.on("close", function() {
|
||||
fs.unlinkSync(temp_path);
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -143,9 +116,11 @@ exports.create_project_readme = function(cb) {
|
|||
|
||||
var is = fs.createReadStream(source);
|
||||
var os = fs.createWriteStream(destination);
|
||||
util.pump(is, os, function(err) {
|
||||
console.log(err);
|
||||
cb(err, file);
|
||||
|
||||
is.pipe(os);
|
||||
|
||||
is.on("close", function() {
|
||||
cb(null, file);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -164,10 +139,12 @@ exports.create_project_gitignore = function(cb) {
|
|||
|
||||
var is = fs.createReadStream(source);
|
||||
var os = fs.createWriteStream(destination);
|
||||
util.pump(is, os, function(err) {
|
||||
console.log(err);
|
||||
cb(err, file);
|
||||
is.pipe(os);
|
||||
|
||||
is.on("close", function() {
|
||||
winston.debug("IN OS END");
|
||||
cb(null, file);
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,31 +1,50 @@
|
|||
var git = require('gitty'),
|
||||
var path = require('path'),
|
||||
db = require('../models/webideModel'),
|
||||
git = require('gitty'),
|
||||
Command = require('../node_modules/gitty/lib/command'),
|
||||
url = require('url'),
|
||||
path = require('path'),
|
||||
winston = require('winston'),
|
||||
fs = require('fs'),
|
||||
fs_helper = require('./fs_helper'),
|
||||
redis = require("redis"),
|
||||
client = redis.createClient(),
|
||||
request_helper = require('./request_helper'),
|
||||
ws_helper = require('./websocket_helper'),
|
||||
config = require('../config/config');
|
||||
|
||||
var REPOSITORY_PATH = path.resolve(__dirname + "/../repositories") + "/";
|
||||
var push_queue = [], pushInterval, PUSH_TIMER = 30000;
|
||||
|
||||
/* extend gitty */
|
||||
git.prototype.remove_recursive = function(path, callback) {
|
||||
var self = this;
|
||||
var cmd = new Command(self, 'rm', ['-r', '--cached'], path);
|
||||
|
||||
cmd.exec(function(error, stdout, stderr) {
|
||||
callback(error || stderr || null);
|
||||
});
|
||||
};
|
||||
|
||||
git.prototype.move = function(source, destination, callback) {
|
||||
var self = this;
|
||||
var cmd = new Command(self, 'mv', [], source, destination);
|
||||
|
||||
cmd.exec(function(error, stdout, stderr) {
|
||||
callback(error || stderr || null);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a simple queue that is used for pushing git changes to the remote repositories.
|
||||
* The queue is currently set using the PUSH_TIMER to delay the remote pushes.
|
||||
*/
|
||||
function push_queue_interval() {
|
||||
console.log('git push queue init');
|
||||
winston.debug('git push queue init');
|
||||
function push(repository_path, remote, branch, username) {
|
||||
git.push(repository_path, remote, branch, function(obj) {
|
||||
require('../server').get_socket(username, function(socket) {
|
||||
if (obj.error) {
|
||||
winston.error(obj);
|
||||
socket.emit('git-push-error', {err: "Error: Failure pushing code to remote repository"});
|
||||
}
|
||||
//console.log(obj);
|
||||
});
|
||||
var repo = git(repository_path);
|
||||
repo.push(remote, branch, function(err) {
|
||||
if (err) {
|
||||
winston.error(err);
|
||||
ws_helper.send_message(null, 'git-push-error', {err: "Error: Failure pushing code to remote repository"});
|
||||
}
|
||||
//winston.debug(obj);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +54,7 @@ function push_queue_interval() {
|
|||
}
|
||||
|
||||
while(push_queue.length > 0) {
|
||||
console.log('pushing code to remote repository');
|
||||
winston.debug('pushing code to remote repository');
|
||||
var element = push_queue.shift();
|
||||
push(element.repository_path, element.remote, element.branch, element.username);
|
||||
}
|
||||
|
|
@ -50,8 +69,8 @@ push_queue_interval();
|
|||
exports.clone_adafruit_libraries = function(adafruit_repository, remote, cb) {
|
||||
fs_helper.check_for_repository(adafruit_repository, function(err, status) {
|
||||
if (!err && !status) {
|
||||
git.clone(REPOSITORY_PATH, remote, function(output) {
|
||||
console.log(output);
|
||||
git.clone(REPOSITORY_PATH, remote, function(err) {
|
||||
winston.debug(err);
|
||||
cb(true);
|
||||
});
|
||||
} else {
|
||||
|
|
@ -60,75 +79,46 @@ exports.clone_adafruit_libraries = function(adafruit_repository, remote, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* This does a few things in order to clone a repository, and save it to your Bitbucket profile.
|
||||
* This allows you to clone from any remote repository, including Github (it's overly complicated...).
|
||||
* 1. It first checks if the repository already exists in your bitbucket profile.
|
||||
* 2. If not 1, it creates the repository in Bitbucket using the API.
|
||||
* 3. It then clones the remote repository you're interested in.
|
||||
* 4. It then updates the git remote for that repository to your bitbucket repository.
|
||||
* 5. Finally, it pushes the cloned repository to your remote account.
|
||||
*/
|
||||
exports.clone_update_remote_push = function(profile, repository_url, retain_remote, cb) {
|
||||
exports.clone_update_remote_push = function(repository_url, cb) {
|
||||
var self = this;
|
||||
|
||||
var repository_name = path.basename(repository_url, '.git');
|
||||
|
||||
if (config.editor.offline || config.editor.github || (retain_remote === 'on')) {
|
||||
self.clone_repository(repository_url, function(err, results) {
|
||||
console.log("clone repository locally: " + repository_name);
|
||||
cb(err, true);
|
||||
});
|
||||
} else {
|
||||
request_helper.list_repositories(profile, function(err, list) {
|
||||
var exists = list.some(function(repository) {
|
||||
return (repository.name === repository_name);
|
||||
});
|
||||
if (!exists) {
|
||||
//TODO need better error handling eventually
|
||||
request_helper.create_repository(profile, repository_name, function(err, response) {
|
||||
console.log("created repository in bitbucket: " + repository_name);
|
||||
self.clone_repository(repository_url, function(err, results) {
|
||||
console.log("clone repository locally: " + repository_name);
|
||||
self.update_remote(profile, repository_name, function(err, response) {
|
||||
console.log("updated remote for repository: " + repository_name);
|
||||
self.push(repository_name, "origin", "master", profile, function(err, response) {
|
||||
console.log("git push for repository: " + repository_name);
|
||||
cb(err, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (repository_url.toLowerCase().indexOf("bitbucket.org") === -1) {
|
||||
cb("Repository Already Exists in Bitbucket, clone with Bitbucket URL.", false);
|
||||
} else {
|
||||
self.clone_repository(repository_url, function(err, results) {
|
||||
console.log("clone repository locally: " + repository_name);
|
||||
cb(err, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.clone_repository(repository_url, function(err, results) {
|
||||
winston.debug("clone repository locally: " + repository_name);
|
||||
cb(err, true);
|
||||
});
|
||||
};
|
||||
|
||||
exports.clone_repository = function(repository_path, cb) {
|
||||
console.log(repository_path);
|
||||
winston.debug("clone_repository", repository_path);
|
||||
var repository_url = url.parse(repository_path);
|
||||
|
||||
console.log("cloning", repository_path);
|
||||
git.clone(REPOSITORY_PATH, repository_url.href, function(output) {
|
||||
cb(output.error, output.message);
|
||||
winston.debug("cloning", repository_path);
|
||||
|
||||
git.clone(REPOSITORY_PATH, repository_url.href, function(err, output) {
|
||||
cb(err, output);
|
||||
});
|
||||
};
|
||||
|
||||
exports.create_local_repository = function(name, cb) {
|
||||
winston.debug("create_repository", name);
|
||||
//create directory
|
||||
var repository_path = REPOSITORY_PATH + name;
|
||||
if (!fs.existsSync(repository_path)){
|
||||
fs.mkdirSync(repository_path);
|
||||
}
|
||||
|
||||
var repo = git(repository_path);
|
||||
repo.init(function(err, output) {
|
||||
cb(err, output);
|
||||
});
|
||||
};
|
||||
|
||||
exports.validate_config = function validate_config(cb) {
|
||||
git.config("user.email", null, function(err, email) {
|
||||
git.config("user.name", null, function(err, name) {
|
||||
git.getConfig("user.email", function(err, email) {
|
||||
git.getConfig("user.name", function(err, name) {
|
||||
if (err) winston.error("git_helper.validate_config err", err);
|
||||
|
||||
if (name && email) {
|
||||
cb(true);
|
||||
} else {
|
||||
|
|
@ -142,15 +132,15 @@ exports.set_config = function(cb) {
|
|||
var self = this;
|
||||
self.validate_config(function(is_valid) {
|
||||
if (is_valid) {
|
||||
console.log('git config is valid');
|
||||
winston.debug('git config is valid');
|
||||
cb();
|
||||
} else {
|
||||
winston.error('git config is invalid');
|
||||
client.hgetall('user', function (err, user) {
|
||||
console.log("set_config user", user);
|
||||
git.config("user.email", user.email, function(err, email) {
|
||||
git.config("user.name", user.name, function(err, name) {
|
||||
console.log("git config set", email, name);
|
||||
db.findOne({type: "user"}, function (err, user) {
|
||||
winston.debug("set_config user", user);
|
||||
git.setConfig("user.email", user.email, function(err, email) {
|
||||
git.setConfig("user.name", user.name, function(err, name) {
|
||||
winston.debug("git config set", email, name);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
|
@ -160,24 +150,14 @@ exports.set_config = function(cb) {
|
|||
|
||||
};
|
||||
|
||||
/*
|
||||
* Updates the remote repository to the users bitbucket repository.
|
||||
*/
|
||||
exports.update_remote = function(profile, repository, cb) {
|
||||
var remote_url = "ssh://git@bitbucket.org/" + profile.username + "/" + repository.toLowerCase() + ".git";
|
||||
git.remote.update(REPOSITORY_PATH + repository, "origin", remote_url, function(output) {
|
||||
//console.log(output);
|
||||
cb(output.error, output.message);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Adds an additional remote to a repository.
|
||||
*/
|
||||
exports.add_remote = function(repository, remote_name, remote_url, cb) {
|
||||
git.remote.add(REPOSITORY_PATH + repository, remote_name, remote_url, function(output) {
|
||||
//console.log(output);
|
||||
cb(output.error, output.message);
|
||||
var repo = git(REPOSITORY_PATH + repository);
|
||||
repo.addRemote(remote_name, remote_url, function(err, message) {
|
||||
winston.debug(err);
|
||||
cb(err, message);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -191,10 +171,10 @@ exports.add = function add(repository, files, cb) {
|
|||
files = [files];
|
||||
}
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
git.add(repository_path, files, function(output) {
|
||||
//console.log(output.errors);
|
||||
//console.log(output);
|
||||
cb(output.errors, output.added);
|
||||
var repo = git(repository_path);
|
||||
repo.add(files, function(err, added) {
|
||||
winston.debug(err);
|
||||
cb(err, added);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -208,9 +188,10 @@ exports.remove = function remove(repository, files, cb) {
|
|||
files = [files];
|
||||
}
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
git.remove(repository_path, files, function(output) {
|
||||
//console.log(output.errors);
|
||||
cb(output.errors, output.added);
|
||||
var repo = git(repository_path);
|
||||
repo.remove(files, function(err, added) {
|
||||
winston.debug(err);
|
||||
cb(err, added);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -222,9 +203,10 @@ exports.remove = function remove(repository, files, cb) {
|
|||
exports.remove_recursive = function remove_recursive(repository, path, cb) {
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
|
||||
git.remove_recursive(repository_path, path, function(output) {
|
||||
console.log(output);
|
||||
cb(output.errors, output.added);
|
||||
var repo = git(repository_path);
|
||||
repo.remove_recursive(path, function(err, data) {
|
||||
winston.debug(err);
|
||||
cb(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -234,9 +216,10 @@ exports.remove_recursive = function remove_recursive(repository, path, cb) {
|
|||
*/
|
||||
exports.move = function move(repository, source, destination, cb) {
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
git.move(repository_path, source, destination, function(obj) {
|
||||
//console.log(obj);
|
||||
cb(obj.error, obj.message);
|
||||
var repo = git(repository_path);
|
||||
repo.move(source, destination, function(err, message) {
|
||||
//winston.debug(obj);
|
||||
cb(err, message);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -247,10 +230,11 @@ exports.move = function move(repository, source, destination, cb) {
|
|||
*/
|
||||
exports.commit = function commit(repository, message, cb) {
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
console.log(repository_path);
|
||||
git.commit(repository_path, message, function(obj) {
|
||||
//console.log(obj);
|
||||
cb(obj.error, obj.message);
|
||||
winston.debug(repository_path);
|
||||
var repo = git(repository_path);
|
||||
repo.commit(message, function(err, message) {
|
||||
//winston.debug(obj);
|
||||
cb(err, message);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -265,9 +249,10 @@ exports.is_modified = function (file, cb) {
|
|||
var item_path = path_array.slice(3).join('/');
|
||||
|
||||
var is_modified = false;
|
||||
git.status(repository_path, function(output) {
|
||||
var repo = git(repository_path);
|
||||
repo.status(function(err, output) {
|
||||
|
||||
console.log(output);
|
||||
winston.debug(err, output);
|
||||
|
||||
if (output.not_staged.length > 0) {
|
||||
output.not_staged.forEach(function(item, index) {
|
||||
|
|
@ -281,7 +266,7 @@ exports.is_modified = function (file, cb) {
|
|||
is_modified = true;
|
||||
}
|
||||
|
||||
cb(output.errors, is_modified);
|
||||
cb(err, is_modified);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -295,18 +280,19 @@ exports.is_untracked = function (file, cb) {
|
|||
var repository_path = path.resolve(REPOSITORY_PATH, repository);
|
||||
var item_path = path_array.slice(3).join('/');
|
||||
|
||||
console.log(item_path);
|
||||
winston.debug(item_path);
|
||||
|
||||
var is_untracked = false;
|
||||
git.status(repository_path, function(output) {
|
||||
var repo = git(repository_path);
|
||||
repo.status(function(err, output) {
|
||||
|
||||
console.log(output);
|
||||
winston.debug(err, output);
|
||||
|
||||
if (output.untracked.indexOf(item_path) !== -1) {
|
||||
is_untracked = true;
|
||||
}
|
||||
|
||||
cb(output.errors, is_untracked);
|
||||
cb(err, is_untracked);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -314,10 +300,10 @@ exports.is_untracked = function (file, cb) {
|
|||
* git push the committed changes. Adds it to the push queue.
|
||||
* repository: the name of the repository that resides in the repositories folder.
|
||||
*/
|
||||
exports.push = function push(repository, remote, branch, profile, cb) {
|
||||
exports.push = function push(repository, remote, branch, cb) {
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
var key = repository + remote + branch;
|
||||
console.log('called push ' + key);
|
||||
winston.debug('called push ' + key);
|
||||
|
||||
//if the repository, remote and branch are already on the queue, just skip it...otherwise add it to the end
|
||||
if (push_queue.length > 0) {
|
||||
|
|
@ -325,14 +311,13 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
|||
if (push_queue[i].key === key) {
|
||||
break;
|
||||
} else {
|
||||
console.log('added to queue ' + key);
|
||||
winston.debug('added to queue ' + key);
|
||||
push_queue.push({
|
||||
key: key,
|
||||
repository_path: repository_path,
|
||||
repository: repository,
|
||||
remote: remote,
|
||||
branch: branch,
|
||||
username: profile ? profile.username : ''
|
||||
branch: branch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -342,8 +327,7 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
|||
repository_path: repository_path,
|
||||
repository: repository,
|
||||
remote: remote,
|
||||
branch: branch,
|
||||
username: profile ? profile.username : ''
|
||||
branch: branch
|
||||
});
|
||||
}
|
||||
cb();
|
||||
|
|
@ -355,29 +339,29 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
|||
*/
|
||||
exports.pull = function pull(repository, remote, branch, cb) {
|
||||
var repository_path = REPOSITORY_PATH + repository;
|
||||
git.pull(repository_path, remote, branch, function(obj) {
|
||||
//console.log(obj);
|
||||
if (obj.error) {
|
||||
winston.error(obj.error);
|
||||
cb("Error: Failure updating from remote repository", obj.message);
|
||||
var repo = git(repository_path);
|
||||
repo.pull(remote, branch, function(err, message) {
|
||||
if (err) {
|
||||
winston.error(err);
|
||||
cb("Error: Failure updating from remote repository", message);
|
||||
} else {
|
||||
cb(null, obj.message);
|
||||
cb(null, message);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Simply removes a file or directory, commits it, and pushes it out.
|
||||
*/
|
||||
exports.remove_commit_push = function(item, profile, cb) {
|
||||
exports.remove_commit_push = function(item, cb) {
|
||||
var self = this;
|
||||
console.log(item);
|
||||
winston.debug(item);
|
||||
var path_array = item.path.split('/');
|
||||
var repository = path_array[2];
|
||||
var item_path = path_array.slice(3).join('/');
|
||||
console.log(item_path);
|
||||
console.log(repository);
|
||||
winston.debug(item_path);
|
||||
winston.debug(repository);
|
||||
|
||||
|
||||
if (item.type === 'directory') {
|
||||
|
|
@ -392,7 +376,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
|||
cb("Error: Failure comitting removed folder", status);
|
||||
return;
|
||||
}
|
||||
self.push(repository, "origin", "master", profile, function() {
|
||||
self.push(repository, "origin", "master", function() {
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
|
@ -409,7 +393,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
|||
cb("Error: Failure comitting removed file", status);
|
||||
return;
|
||||
}
|
||||
self.push(repository, "origin", "master", profile, function() {
|
||||
self.push(repository, "origin", "master", function() {
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
|
@ -420,7 +404,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
|||
/*
|
||||
* Simply moves a file or directory, commits it, and pushes it out.
|
||||
*/
|
||||
exports.move_commit_push = function(item, profile, cb) {
|
||||
exports.move_commit_push = function(item, cb) {
|
||||
var self = this;
|
||||
var path_array = item.path.split('/');
|
||||
var repository = path_array[2];
|
||||
|
|
@ -439,18 +423,18 @@ exports.move_commit_push = function(item, profile, cb) {
|
|||
self.move(repository, item_path, destination_path, function(err, status) {
|
||||
var commit_message = "Moved " + item.name;
|
||||
if (err) {
|
||||
console.log ("has error returning");
|
||||
winston.debug ("has error returning");
|
||||
cb("Error: Failure moving file (renaming)");
|
||||
return;
|
||||
}
|
||||
self.commit(repository, commit_message, function(err, status) {
|
||||
console.log("Committed Moved File");
|
||||
winston.debug("Committed Moved File");
|
||||
if (err) {
|
||||
cb("Error: Failure comitting file into git");
|
||||
return;
|
||||
}
|
||||
self.push(repository, "origin", "master", profile, function() {
|
||||
console.log("Pushed latest changes");
|
||||
self.push(repository, "origin", "master", function() {
|
||||
winston.debug("Pushed latest changes");
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
|
@ -463,7 +447,7 @@ exports.move_commit_push = function(item, profile, cb) {
|
|||
/*
|
||||
* Simply commits a file or directory, commits it, and pushes it out.
|
||||
*/
|
||||
exports.commit_push_and_save = function(file, commit_message, profile, cb) {
|
||||
exports.commit_push_and_save = function(file, commit_message, cb) {
|
||||
var self = this,
|
||||
path_array, repository, file_path;
|
||||
if (!file.repository) {
|
||||
|
|
@ -475,26 +459,26 @@ exports.commit_push_and_save = function(file, commit_message, profile, cb) {
|
|||
file_path = file.path;
|
||||
}
|
||||
|
||||
console.log(commit_message);
|
||||
winston.debug(commit_message);
|
||||
|
||||
|
||||
|
||||
self.add(repository, file_path, function(err, status) {
|
||||
console.log("added", err, status);
|
||||
winston.debug("added", err, status);
|
||||
if (err && err.length > 0) {
|
||||
cb("Error: Failure adding file to git", status);
|
||||
return;
|
||||
}
|
||||
self.commit(repository, commit_message, function(err, status) {
|
||||
console.log("committed", err, status);
|
||||
winston.debug("committed", err, status);
|
||||
if (err && err.length > 0) {
|
||||
cb("Error: Failure comitting file into git", status);
|
||||
return;
|
||||
}
|
||||
self.push(repository, "origin", "master", profile, function() {
|
||||
console.log("added to push queue");
|
||||
self.push(repository, "origin", "master", function() {
|
||||
winston.debug("added to push queue");
|
||||
cb();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
var spawn = require('child_process').spawn,
|
||||
exec = require('child_process').exec,
|
||||
db = require('../../models/webideModel'),
|
||||
net = require('net'),
|
||||
path = require('path'),
|
||||
ws_helper = require('../websocket_helper'),
|
||||
debug_program, debug_client,
|
||||
client_connected = false,
|
||||
HOST = '127.0.0.1',
|
||||
|
|
@ -28,39 +30,46 @@ exports.start_debug = function start_debug(file, socket) {
|
|||
console.log(!debug_program);
|
||||
if (!debug_program) {
|
||||
console.log('spawn debugger');
|
||||
debug_program = spawn("sudo", ["python", "debugger.py"], {cwd: __dirname});
|
||||
var buffer = "";
|
||||
debug_program.stdout.on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
|
||||
buffer += data.toString();
|
||||
|
||||
if (buffer.indexOf("DEBUGGER READY") !== -1 && !client_connected) {
|
||||
console.log("DEBUGGER READY");
|
||||
connect_client(file, socket);
|
||||
console.log("after connect_client");
|
||||
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||
var command = 'python';
|
||||
if (typeof settings !== 'undefined' && settings.python_version === '3') {
|
||||
command = 'python3';
|
||||
}
|
||||
|
||||
});
|
||||
debug_program = spawn("sudo", [command, "debugger.py"], {cwd: __dirname});
|
||||
var buffer = "";
|
||||
debug_program.stdout.on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
|
||||
debug_program.stderr.on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
socket.emit('debug-error', {file: file, error: data});
|
||||
});
|
||||
buffer += data.toString();
|
||||
|
||||
debug_program.on('error', function(data) {
|
||||
console.log("DEBUG PROGRAM ERROR:");
|
||||
console.log(data);
|
||||
});
|
||||
if (buffer.indexOf("DEBUGGER READY") !== -1 && !client_connected) {
|
||||
console.log("DEBUGGER READY");
|
||||
connect_client(file, socket);
|
||||
console.log("after connect_client");
|
||||
}
|
||||
|
||||
debug_program.on('exit', function(code) {
|
||||
console.log('Debug Program Exit');
|
||||
console.log(code);
|
||||
debug_program = null;
|
||||
});
|
||||
|
||||
if (enable_debug) {
|
||||
self.start_debug(file, socket);
|
||||
}
|
||||
debug_program.stderr.on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
ws_helper.send_message(socket, 'debug-error', {file: file, error: data});
|
||||
});
|
||||
|
||||
debug_program.on('error', function(data) {
|
||||
console.log("DEBUG PROGRAM ERROR:");
|
||||
console.log(data);
|
||||
});
|
||||
|
||||
debug_program.on('exit', function(code) {
|
||||
console.log('Debug Program Exit');
|
||||
console.log(code);
|
||||
debug_program = null;
|
||||
|
||||
if (enable_debug) {
|
||||
self.start_debug(file, socket);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
//console.log('resetting debugger');
|
||||
|
|
@ -82,6 +91,7 @@ function connect_client(file, socket) {
|
|||
debug_client = new net.Socket();
|
||||
debug_client.connect(PORT, HOST, function() {
|
||||
socket.emit('debug-client-connected');
|
||||
ws_helper.send_message(socket, 'debug-client-connected', "");
|
||||
client_connected = true;
|
||||
console.log('connected to python debugger: ' + HOST + ':' + PORT);
|
||||
console.log(file_path);
|
||||
|
|
@ -95,7 +105,7 @@ function connect_client(file, socket) {
|
|||
var temp_buff = buffer.split('\n');
|
||||
for (var i=0; i<temp_buff.length-1; i++) {
|
||||
console.log(JSON.parse(temp_buff[i]));
|
||||
socket.emit('debug-file-response', JSON.parse(temp_buff[i]));
|
||||
ws_helper.send_message(socket, 'debug-file-response', JSON.parse(temp_buff[i]));
|
||||
}
|
||||
|
||||
buffer = temp_buff.slice(temp_buff.length);
|
||||
|
|
|
|||
|
|
@ -1,110 +0,0 @@
|
|||
var request = require('request'),
|
||||
qs = require('querystring'),
|
||||
fs_helper = require('./fs_helper');
|
||||
|
||||
/*
|
||||
* Call the Bitbucket OAuth API to post the ssh key to the users profile.
|
||||
*/
|
||||
exports.post_ssh_key = function(profile, cb) {
|
||||
var url = "https://api.bitbucket.org/1.0/ssh-keys/";
|
||||
var oauth = { consumer_key: profile.consumer_key,
|
||||
consumer_secret: profile.consumer_secret,
|
||||
token: profile.token,
|
||||
token_secret: profile.token_secret };
|
||||
|
||||
fs_helper.read_or_generate_key(function(data) {
|
||||
var params = { key: data.trim(), label: 'raspeditor'};
|
||||
|
||||
request.post({
|
||||
url:url,
|
||||
body: qs.stringify(params),
|
||||
oauth:oauth
|
||||
}, function (e, r, body) {
|
||||
console.log(e);
|
||||
console.log(r.statusCode);
|
||||
console.log(body);
|
||||
cb (e, body);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Call the Bitbucket OAuth API to createa a repository on the users profile.
|
||||
*/
|
||||
exports.set_repository_private = function set_repository_private(profile, repository_name) {
|
||||
var username = profile.username;
|
||||
//console.log('set_repository_private');
|
||||
//console.log(profile);
|
||||
var url = "https://api.bitbucket.org/1.0/repositories/" + username + "/" + repository_name;
|
||||
var oauth = { consumer_key: profile.consumer_key,
|
||||
consumer_secret: profile.consumer_secret,
|
||||
token: profile.token,
|
||||
token_secret: profile.token_secret };
|
||||
|
||||
|
||||
var params = {is_private: true};
|
||||
|
||||
request.put({
|
||||
url:url,
|
||||
body: qs.stringify(params),
|
||||
oauth:oauth
|
||||
}, function (e, r, body) {
|
||||
//console.log(e);
|
||||
console.log(r.statusCode);
|
||||
if (r.statusCode === 200) {
|
||||
console.log("successfully set repository private");
|
||||
}
|
||||
//console.log(body);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Call the Bitbucket OAuth API to get a list of the repositories on the users profile.
|
||||
*/
|
||||
exports.list_repositories = function(profile, cb) {
|
||||
var self = this;
|
||||
var url = "https://api.bitbucket.org/1.0/user/repositories/";
|
||||
var oauth = { consumer_key: profile.consumer_key,
|
||||
consumer_secret: profile.consumer_secret,
|
||||
token: profile.token,
|
||||
token_secret: profile.token_secret };
|
||||
|
||||
request.get({
|
||||
url:url,
|
||||
oauth:oauth,
|
||||
json: true
|
||||
}, function (e, r, body) {
|
||||
console.log(e);
|
||||
//console.log(r.statusCode);
|
||||
//console.log(body);
|
||||
cb (e, body);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Call the Bitbucket OAuth API to createa a repository on the users profile.
|
||||
*/
|
||||
exports.create_repository = function(profile, repository_name, cb) {
|
||||
var url = "https://api.bitbucket.org/1.0/repositories/";
|
||||
var oauth = { consumer_key: profile.consumer_key,
|
||||
consumer_secret: profile.consumer_secret,
|
||||
token: profile.token,
|
||||
token_secret: profile.token_secret };
|
||||
|
||||
|
||||
var params = { name: repository_name, scm: 'git', is_private: true};
|
||||
|
||||
request.post({
|
||||
url:url,
|
||||
body: qs.stringify(params),
|
||||
oauth:oauth
|
||||
}, function (e, r, body) {
|
||||
console.log(e);
|
||||
console.log(r.statusCode);
|
||||
console.log(body);
|
||||
cb (e, body);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
var exec = require('child_process').exec,
|
||||
fs = require ('fs'),
|
||||
path = require('path'),
|
||||
winston = require('winston'),
|
||||
exec_helper = require('./exec_helper'),
|
||||
redis = require('redis'),
|
||||
client = redis.createClient(),
|
||||
later = require('later').later;
|
||||
enParser = require('later').enParser,
|
||||
job_queue = [];
|
||||
var path = require('path'),
|
||||
db = require('../models/jobModel'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require ('fs'),
|
||||
winston = require('winston'),
|
||||
exec_helper = require('./exec_helper'),
|
||||
ws_helper = require('./websocket_helper'),
|
||||
later = require('later'),
|
||||
job_queue = [];
|
||||
|
||||
fs.exists || (fs.exists = path.exists);
|
||||
|
||||
|
|
@ -20,96 +19,88 @@ function execute_job(file) {
|
|||
console.log("execute_job");
|
||||
console.log(file.key);
|
||||
|
||||
client.hmset(file.key, "last_run", new Date(), function() {
|
||||
//repopulate the job list in the editor
|
||||
file.last_run = new Date();
|
||||
db.update({key: file.key}, file, {upsert: true}, function(err) {
|
||||
|
||||
});
|
||||
} else {
|
||||
winston.info('scheduled job no longer exists, deleting from queue: ' + file_path);
|
||||
client.del(file.key);
|
||||
client.srem("jobs", file.key);
|
||||
//TODO redis to nedb
|
||||
db.remove({key: file.key});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function schedule_job(key, job) {
|
||||
var is_new_job = true,
|
||||
l = later(60),
|
||||
schedule = enParser().parse(job.text);
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
l.exec(schedule, new Date(), execute_job, job);
|
||||
console.log("Job Scheduled: ", schedule);
|
||||
var is_new_job = true,
|
||||
schedule = later.parse.text(job.text);
|
||||
|
||||
var len = job_queue.length;
|
||||
for (var i=0; i<len; i++) {
|
||||
if (job_queue[i].key === key) {
|
||||
//job already exists, but has been modified, let's stop the existing one
|
||||
job_queue[i].later.stopExec();
|
||||
later.date.localTime();
|
||||
var job_timer = later.setInterval(execute_job.bind(null, job), schedule);
|
||||
console.log("Job Scheduled: ", schedule);
|
||||
|
||||
//replace it in the queue
|
||||
job_queue[i] = {key: key, later: l};
|
||||
var len = job_queue.length;
|
||||
for (var i=0; i<len; i++) {
|
||||
if (job_queue[i].key === key) {
|
||||
//job already exists, but has been modified, let's stop the existing one
|
||||
job_queue[i].job_timer.clear();
|
||||
|
||||
is_new_job = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//replace it in the queue
|
||||
job_queue[i] = {key: key, job_timer: job_timer};
|
||||
|
||||
if (is_new_job) {
|
||||
job_queue.push({key: key, later: l});
|
||||
}
|
||||
is_new_job = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(job_queue);
|
||||
if (is_new_job) {
|
||||
job_queue.push({key: key, job_timer: job_timer});
|
||||
}
|
||||
|
||||
//console.log(job_queue);
|
||||
}
|
||||
|
||||
|
||||
exports.emit_scheduled_jobs = function emit_scheduled_jobs(username, socket) {
|
||||
var job_list = [];
|
||||
client.smembers("jobs", function(err, res) {
|
||||
res.forEach(function(key, i) {
|
||||
client.hgetall(key, function(err, job_data) {
|
||||
if (job_data.username === username) {
|
||||
job_list.push(job_data);
|
||||
}
|
||||
|
||||
if (res.length === (i+1)) {
|
||||
socket.emit('scheduled-job-list', job_list);
|
||||
}
|
||||
});
|
||||
});
|
||||
exports.emit_scheduled_jobs = function emit_scheduled_jobs(socket) {
|
||||
winston.debug("emit_scheduled_jobs");
|
||||
db.find({type: "job"}, function(err, data) {
|
||||
ws_helper.send_message(socket, 'scheduled-job-list', data);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Create new schedule
|
||||
*/
|
||||
exports.add_schedule = function(schedule, socket, session) {
|
||||
exports.add_schedule = function(schedule, socket) {
|
||||
var self = this;
|
||||
schedule.file.username = session.username;
|
||||
var file_path = schedule.file.path.replace('\/filesystem\/', '\/repositories\/');
|
||||
var key = "jobs:" + file_path.replace(/\W/g, ''); //keep only alphanumeric for key
|
||||
var job_data = {
|
||||
type: "job",
|
||||
text: schedule.text,
|
||||
name: schedule.file.name,
|
||||
key: key,
|
||||
last_run: "",
|
||||
active: "1",
|
||||
path: file_path,
|
||||
extension: schedule.file.extension,
|
||||
username: schedule.file.username
|
||||
extension: schedule.file.extension
|
||||
};
|
||||
console.log("add_schedule");
|
||||
console.log(job_data);
|
||||
|
||||
client.sadd("jobs", key, function() {
|
||||
client.hmset(key, job_data, function() {
|
||||
schedule_job(key, job_data);
|
||||
//repopulate the job list in the editor
|
||||
self.emit_scheduled_jobs(session.username, socket);
|
||||
});
|
||||
db.update({key: key}, job_data, {upsert: true}, function(err, numReplaced, upsert) {
|
||||
schedule_job(key, job_data);
|
||||
//repopulate the job list in the editor
|
||||
self.emit_scheduled_jobs(socket);
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete_job = function(key, socket, session) {
|
||||
exports.delete_job = function(key, socket) {
|
||||
var self = this;
|
||||
var len = job_queue.length;
|
||||
for (var i=0; i<len; i++) {
|
||||
|
|
@ -119,24 +110,21 @@ exports.delete_job = function(key, socket, session) {
|
|||
//remove from array
|
||||
job_queue.splice(i, 1);
|
||||
//remove from redis
|
||||
client.del(key);
|
||||
client.srem("jobs", key);
|
||||
db.remove({key: key});
|
||||
//emit change to front-end
|
||||
self.emit_scheduled_jobs(session.username, socket);
|
||||
self.emit_scheduled_jobs(socket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.toggle_job = function(key, socket, session) {
|
||||
exports.toggle_job = function(key, socket) {
|
||||
var self = this;
|
||||
console.log(key);
|
||||
client.hgetall(key, function(err, job) {
|
||||
console.log(job);
|
||||
//toggle status
|
||||
db.findOne({key: key}, function(err, job) {
|
||||
job.active = 1-job.active;
|
||||
|
||||
client.hmset(key, "active", job.active, function() {
|
||||
db.update({key: key}, job, function() {
|
||||
if (!job.active) {
|
||||
//remove job from queue, but not redis
|
||||
var len = job_queue.length;
|
||||
|
|
@ -147,31 +135,24 @@ exports.toggle_job = function(key, socket, session) {
|
|||
//remove from array
|
||||
job_queue.splice(i, 1);
|
||||
//emit change to front-end
|
||||
self.emit_scheduled_jobs(session.username, socket);
|
||||
self.emit_scheduled_jobs(socket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
schedule_job(key, job);
|
||||
//repopulate the job list in the editor
|
||||
self.emit_scheduled_jobs(session.username, socket);
|
||||
self.emit_scheduled_jobs(socket);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Jobs initialized at server startup
|
||||
*/
|
||||
exports.initialize_jobs = function() {
|
||||
client.smembers("jobs", function(err, res) {
|
||||
res.forEach(function(key) {
|
||||
client.hgetall(key, function(err, job_data) {
|
||||
schedule_job(key, job_data);
|
||||
});
|
||||
});
|
||||
db.find({type: "job"}, function(err, data) {
|
||||
schedule_job(data.key, data);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
8
helpers/websocket_helper.js
Normal file
8
helpers/websocket_helper.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var config = require('../config/config');
|
||||
|
||||
exports.send_message = function send_message(ws, type, data) {
|
||||
if (!ws) {
|
||||
ws = config.editor_ws;
|
||||
}
|
||||
ws.send(JSON.stringify({type: type, data: data}));
|
||||
}
|
||||
11
models/jobModel.js
Normal file
11
models/jobModel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
var Datastore = require('nedb'),
|
||||
path = require('path');
|
||||
|
||||
var jobsDb = new Datastore({
|
||||
filename: path.resolve(__dirname, '../db/jobs_data_store'),
|
||||
autoload: true
|
||||
});
|
||||
|
||||
module.exports = jobsDb;
|
||||
11
models/webideModel.js
Normal file
11
models/webideModel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
var Datastore = require('nedb'),
|
||||
path = require('path');
|
||||
|
||||
var webideDb = new Datastore({
|
||||
filename: path.resolve(__dirname, '../db/webide_data_store'),
|
||||
autoload: true
|
||||
});
|
||||
|
||||
module.exports = webideDb;
|
||||
12
monitor.js
Normal file
12
monitor.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
var forever = require('forever-monitor');
|
||||
|
||||
var child = new (forever.Monitor)('server.js', {
|
||||
silent: false,
|
||||
args: []
|
||||
});
|
||||
|
||||
child.on('exit', function () {
|
||||
console.log('your-filename.js has exited after 3 restarts');
|
||||
});
|
||||
|
||||
child.start();
|
||||
0
output.log
Normal file
0
output.log
Normal file
3617
package-lock.json
generated
Normal file
3617
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
39
package.json
39
package.json
|
|
@ -4,21 +4,28 @@
|
|||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"express": "3.1.0",
|
||||
"passport": "0.1.15",
|
||||
"passport-bitbucket": "0.1.2",
|
||||
"passport-github": "0.1.3",
|
||||
"jade": "0.28.1",
|
||||
"request": "2.14.0",
|
||||
"socket.io": "0.9.13",
|
||||
"gitty": "git://github.com/jwcooper/Gitty.git",
|
||||
"jsDAV": "git://github.com/jwcooper/jsDAV.git",
|
||||
"connect": "2.7.3",
|
||||
"connect-redis": "1.x",
|
||||
"redis": "0.8.2",
|
||||
"tty.js": "git://github.com/jwcooper/tty.js.git",
|
||||
"validator": "0.4.25",
|
||||
"winston": "0.6.2",
|
||||
"later": "git://github.com/jwcooper/later.git"
|
||||
"body-parser": "1.18.2",
|
||||
"cookie": "0.2.3",
|
||||
"cookie-parser": "1.4.3",
|
||||
"express": "4.16.2",
|
||||
"express-session": "1.12.1",
|
||||
"express-ws": "3.0.0",
|
||||
"gitty": "^3.6.0",
|
||||
"jsDAV": "jwcooper/jsDAV#629ded2",
|
||||
"later": "^1.2.0",
|
||||
"method-override": "2.3.10",
|
||||
"morgan": "1.9.0",
|
||||
"multer": "^1.3.0",
|
||||
"nedb": "1.8.0",
|
||||
"node-pty": "0.7.4",
|
||||
"pug": "2.0.1",
|
||||
"request": "2.83.0",
|
||||
"serve-static": "1.13.1",
|
||||
"validator": "9.4.0",
|
||||
"winston": "2.4.0",
|
||||
"xterm": "3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"forever-monitor": "^1.7.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -6,7 +6,6 @@ body {
|
|||
}
|
||||
|
||||
#container {
|
||||
padding-top: 40px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
@ -175,7 +174,7 @@ a.navigator-settings i.settings-enabled {
|
|||
float: right;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding-right: 15px;
|
||||
padding: 4px 15px 0 0;
|
||||
}
|
||||
|
||||
#navigator-folder .refresh-directory:hover {
|
||||
|
|
@ -256,7 +255,7 @@ a.navigator-settings i.settings-enabled {
|
|||
.fileinput-button span {
|
||||
font-size: 16px;
|
||||
color: #E4E5E7;
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.navigator-item-upload, .navigator-item-create:nth-child(2) {
|
||||
|
|
@ -301,6 +300,7 @@ a.navigator-settings i.settings-enabled {
|
|||
|
||||
#create-modal .modal-body input[type="text"] {
|
||||
width: 97%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#confirm-modal p {
|
||||
|
|
@ -337,7 +337,7 @@ a.navigator-settings i.settings-enabled {
|
|||
padding: 3px 7px 3px 7px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.rename-submit:hover {
|
||||
|
|
@ -345,6 +345,9 @@ a.navigator-settings i.settings-enabled {
|
|||
}
|
||||
|
||||
.create-input-wrapper input[type='text'], .rename-input-wrapper input[type='text'] {
|
||||
width: 185px;
|
||||
margin: 5px;
|
||||
height: 30px;
|
||||
background-color: #FFFFFF;
|
||||
border: none;
|
||||
-webkit-box-shadow: none;
|
||||
|
|
@ -353,12 +356,7 @@ a.navigator-settings i.settings-enabled {
|
|||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.create-input-wrapper input[type='text'] {
|
||||
width: 185px;
|
||||
margin: 5px;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.rename-input-wrapper {
|
||||
|
|
@ -401,7 +399,8 @@ a.navigator-settings i.settings-enabled {
|
|||
left: 300px;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
bottom: 40px;
|
||||
bottom: 0px;
|
||||
margin-bottom: 40px;
|
||||
border-bottom: 1px solid #EDEDED;
|
||||
}
|
||||
|
||||
|
|
@ -453,9 +452,10 @@ a.navigator-settings i.settings-enabled {
|
|||
#editor, #schedule-manager, #settings-manager {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
right: 0;
|
||||
top: 40px;
|
||||
bottom: 0;
|
||||
margin-bottom: -40px;
|
||||
border-top: 1px solid #EDEDED;
|
||||
border-right: 1px solid #EDEDED;
|
||||
}
|
||||
|
|
@ -525,12 +525,12 @@ a.navigator-settings i.settings-enabled {
|
|||
background-color: #EDEEEE;
|
||||
color: #2F3133;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
margin: 0 1px 0 0;
|
||||
}
|
||||
|
||||
.settings-element .font-size-value, .soft-tab-value, .tab-size-value, .invisibles-value, .manual-git-value {
|
||||
.settings-element .font-size-value, .soft-tab-value, .tab-size-value, .invisibles-value, .manual-git-value, .python-version {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
@ -544,6 +544,7 @@ a.navigator-settings i.settings-enabled {
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
#editor-output {
|
||||
|
|
@ -673,10 +674,6 @@ a.navigator-settings i.settings-enabled {
|
|||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#setup-content .bitbucket-signup {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#setup-content form {
|
||||
}
|
||||
|
||||
|
|
@ -692,6 +689,7 @@ a.navigator-settings i.settings-enabled {
|
|||
|
||||
#setup-content form input[type='text'], #setup-content form input[type='password'] {
|
||||
width: 350px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#setup-content form .skip-button {
|
||||
|
|
@ -755,13 +753,13 @@ a.navigator-settings i.settings-enabled {
|
|||
color: #E4E5E7;
|
||||
}
|
||||
|
||||
.ace_gutter-cell.ace_breakpoint{
|
||||
.ace_gutter-cell.ace_breakpoint{
|
||||
background-color: #BB1142;
|
||||
}
|
||||
|
||||
.debug-line {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
z-index: 5;
|
||||
background-color: #BB1142;
|
||||
}
|
||||
|
||||
|
|
@ -771,4 +769,4 @@ a.navigator-settings i.settings-enabled {
|
|||
|
||||
.debug-link-disabled:hover {
|
||||
cursor: wait;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
-0.8.0
|
||||
Add simple python3 support
|
||||
Fix debug populating variables
|
||||
|
||||
-0.7.0
|
||||
Update pug dependency
|
||||
Updates to installer and uninstaller
|
||||
|
||||
-0.6.0
|
||||
Initial pre-release of the simplified webide
|
||||
|
||||
-0.3.12
|
||||
Add missing cookie package
|
||||
|
||||
-0.3.11
|
||||
Fixes for installation errors
|
||||
Fix some deprecated messages
|
||||
|
||||
-0.3.10
|
||||
Fix for settings being undefined in offline mode
|
||||
|
||||
|
|
@ -15,7 +33,7 @@ Handle file rename errors, including detecting renames with same name.
|
|||
-0.3.7
|
||||
Github support.
|
||||
- Ability to enable with --github as the default
|
||||
- Advanced setting.
|
||||
- Advanced setting.
|
||||
- Requires manual ssh key setup as of yet.
|
||||
- Most commands are treated as manual mode for now (manual commits, etc).
|
||||
New Offline mode
|
||||
|
|
@ -220,4 +238,4 @@ Show update notes in editor while updating
|
|||
Fix for path issues with new editor file structure.
|
||||
|
||||
-0.0.5
|
||||
Add login page styling
|
||||
Add login page styling
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
0.3.8
|
||||
http://adafruit-download.s3.amazonaws.com/webide-0.3.8-update.tar.gz
|
||||
https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/changelog.txt
|
||||
0.8.0
|
||||
https://github.com/adafruit/Adafruit-WebIDE/archive/0.8.0.tar.gz
|
||||
https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/changelog.txt
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
# for examples
|
||||
|
||||
# If not running interactively, don't do anything
|
||||
[ -z "$PS1" ] && return
|
||||
case $- in
|
||||
*i*) ;;
|
||||
*) return;;
|
||||
esac
|
||||
|
||||
# don't put duplicate lines or lines starting with space in the history.
|
||||
# See bash(1) for more options
|
||||
|
|
@ -28,13 +31,13 @@ shopt -s checkwinsize
|
|||
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||
|
||||
# set variable identifying the chroot you work in (used in the prompt below)
|
||||
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
|
||||
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||
debian_chroot=$(cat /etc/debian_chroot)
|
||||
fi
|
||||
|
||||
# set a fancy prompt (non-color, unless we know we "want" color)
|
||||
case "$TERM" in
|
||||
xterm-color) color_prompt=yes;;
|
||||
xterm-color|*-256color) color_prompt=yes;;
|
||||
esac
|
||||
|
||||
# uncomment for a colored prompt, if the terminal has the capability; turned
|
||||
|
|
@ -44,17 +47,17 @@ force_color_prompt=yes
|
|||
|
||||
if [ -n "$force_color_prompt" ]; then
|
||||
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||
# We have color support; assume it's compliant with Ecma-48
|
||||
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||
# a case would tend to support setf rather than setaf.)
|
||||
color_prompt=yes
|
||||
# We have color support; assume it's compliant with Ecma-48
|
||||
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||
# a case would tend to support setf rather than setaf.)
|
||||
color_prompt=yes
|
||||
else
|
||||
color_prompt=
|
||||
color_prompt=
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$color_prompt" = yes ]; then
|
||||
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w \$\[\033[00m\] '
|
||||
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
|
||||
else
|
||||
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
||||
fi
|
||||
|
|
@ -81,6 +84,9 @@ if [ -x /usr/bin/dircolors ]; then
|
|||
alias egrep='egrep --color=auto'
|
||||
fi
|
||||
|
||||
# colored GCC warnings and errors
|
||||
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
|
||||
|
||||
# some more ls aliases
|
||||
#alias ll='ls -l'
|
||||
#alias la='ls -A'
|
||||
|
|
@ -98,6 +104,10 @@ fi
|
|||
# enable programmable completion features (you don't need to enable
|
||||
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
||||
# sources /etc/bash.bashrc).
|
||||
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
|
||||
if ! shopt -oq posix; then
|
||||
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||
. /usr/share/bash-completion/bash_completion
|
||||
elif [ -f /etc/bash_completion ]; then
|
||||
. /etc/bash_completion
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
22
scripts/.profile
Normal file
22
scripts/.profile
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# ~/.profile: executed by the command interpreter for login shells.
|
||||
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
|
||||
# exists.
|
||||
# see /usr/share/doc/bash/examples/startup-files for examples.
|
||||
# the files are located in the bash-doc package.
|
||||
|
||||
# the default umask is set in /etc/profile; for setting the umask
|
||||
# for ssh logins, install and configure the libpam-umask package.
|
||||
#umask 022
|
||||
|
||||
# if running bash
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/bin" ] ; then
|
||||
PATH="$HOME/bin:$PATH"
|
||||
fi
|
||||
19
scripts/adafruit-webide.service
Normal file
19
scripts/adafruit-webide.service
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[Unit]
|
||||
Description=Adafruit-WebIDE
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/node /usr/share/adafruit/webide/server.js
|
||||
WorkingDirectory=/usr/share/adafruit/webide
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=webide
|
||||
# Change to a non-root user
|
||||
User=webide
|
||||
Group=webide
|
||||
# Set environment options
|
||||
Environment=NODE_ENV=production PORT=8080
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -23,8 +23,8 @@ set(CPACK_PACKAGE_CONTACT "support@adafruit.com")
|
|||
set(CPACK_PACKAGE_VENDOR "Adafruit")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "7")
|
||||
set(CPACK_PACKAGE_VERSION "0.3.7")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "12")
|
||||
set(CPACK_PACKAGE_VERSION "0.3.12")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Adafruit WebIDE")
|
||||
set(CPACK_RESOURCE_FILE_README "${EDITOR_DIR}/README.md")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${EDITOR_DIR}/GNU-AGPL-3.0")
|
||||
|
|
@ -33,8 +33,8 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Adafruit")
|
|||
set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-ubuntu")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "nodejs, nodejs-legacy, redis-server, git, restartd, libcap2-bin, avahi-daemon, i2c-tools, python-smbus")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "nodejs, nodejs-legacy, redis-server, git, avahi-daemon, i2c-tools, python-smbus")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst;${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm;")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
||||
|
||||
include(CPack)
|
||||
include(CPack)
|
||||
|
|
|
|||
|
|
@ -15,17 +15,6 @@ echo 'webide "node" "service adafruit-webide.sh restart" ""' >> /etc/restartd.co
|
|||
|
||||
cd /etc/init.d
|
||||
|
||||
NODE_PATH=""
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
if [ $ARCH = armhf ]; then
|
||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_hf\/node"
|
||||
chmod +x "$WEBIDE_ROOT/bin/node_hf/node"
|
||||
else
|
||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_sf\/node"
|
||||
chmod +x "$WEBIDE_ROOT/bin/node_sf/node"
|
||||
fi
|
||||
sed -i "s/NODE_PATH/$NODE_PATH/g" adafruit-webide.sh
|
||||
|
||||
update-rc.d adafruit-webide.sh defaults
|
||||
|
||||
echo "Attempting to force reload date and time from ntp server"
|
||||
|
|
@ -58,4 +47,4 @@ echo "**** The Adafruit WebIDE is installed and running! ****"
|
|||
echo "**** Commands: sudo service adafruit-webide.sh {start,stop,restart} ****"
|
||||
echo "**** Navigate to http://$(hostname).local$PORT_USED to use the WebIDE"
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ echo "Attempting to force reload date and time from ntp server"
|
|||
/usr/bin/ntpdate -b -s -u pool.ntp.org
|
||||
|
||||
echo "**** Downloading the latest version of the WebIDE ****"
|
||||
curl -L http://adafruit-download.s3.amazonaws.com/webide-0.3.8.tar.gz | tar xzf -
|
||||
curl -L https://adafruit-download.s3.amazonaws.com/webide-0.3.12.tar.gz | tar xzf -
|
||||
|
||||
echo "**** Installing required libraries ****"
|
||||
echo "**** (redis-server git avahi-daemon i2c-tools python-smbus openssh-keygen) ****"
|
||||
opkg update
|
||||
opkg install nodejs git avahi-daemon i2c-tools python-smbus libcap2 libcap-bin openssh-keygen
|
||||
opkg install nodejs git avahi-daemon i2c-tools python-smbus openssh-keygen
|
||||
|
||||
if ! redis-cli PING
|
||||
then
|
||||
|
|
@ -87,7 +87,7 @@ then
|
|||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/redis/redis_6379 > /etc/init.d/redis_6379
|
||||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/redis/redis.conf > /etc/redis/6379.conf
|
||||
mkdir -p /var/redis/6379
|
||||
chmod +x /etc/init.d/redis_6379
|
||||
chmod +x /etc/init.d/redis_6379
|
||||
update-rc.d redis_6379 defaults
|
||||
/etc/init.d/redis_6379 start
|
||||
cd "$WEBIDE_ROOT"
|
||||
|
|
|
|||
|
|
@ -53,29 +53,25 @@ WEBIDE_ROOT="/usr/share/adafruit/webide"
|
|||
#needed for SSH key and config access at this point.
|
||||
WEBIDE_HOME="/home/webide"
|
||||
|
||||
#NODE_PATH="/usr/local/lib/node"
|
||||
|
||||
#if [ ! -d "$NODE_PATH" ]; then
|
||||
# mkdir -p "$NODE_PATH"
|
||||
# # Control will enter here if $DIRECTORY doesn't exist.
|
||||
#fi
|
||||
|
||||
mkdir -p "$WEBIDE_ROOT"
|
||||
mkdir -p "$WEBIDE_HOME"
|
||||
mkdir -p "$WEBIDE_HOME/tmp"
|
||||
cd "$WEBIDE_ROOT"
|
||||
|
||||
echo "**** Downloading the latest version of the WebIDE ****"
|
||||
curl -L http://adafruit-download.s3.amazonaws.com/webide-0.3.8.tar.gz | tar xzf -
|
||||
curl -L https://github.com/adafruit/Adafruit-WebIDE/archive/0.8.0.tar.gz | tar xzf - --strip-components=1
|
||||
|
||||
echo "**** Installing required libraries ****"
|
||||
echo "**** (redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus) ****"
|
||||
echo "**** (nodejs-legacy npm git i2c-tools python-smbus ntp libkrb5-dev) ****"
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
apt-get update
|
||||
apt-get install nodejs nodejs-legacy redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus ntp -y
|
||||
apt-get install nodejs git i2c-tools python-smbus ntp libkrb5-dev -y
|
||||
npm install -g npm
|
||||
|
||||
echo "**** Create webide user and group ****"
|
||||
groupadd webide || true
|
||||
useradd -g webide webide || true
|
||||
usermod -a -G i2c,sudo webide || true
|
||||
chsh -s /bin/bash webide
|
||||
|
||||
echo "**** Adding webide user to sudoers ****"
|
||||
if [ -f "/etc/sudoers.tmp" ]; then
|
||||
|
|
@ -93,75 +89,28 @@ chown -R webide:webide "$WEBIDE_HOME"
|
|||
chown -R webide:webide "$WEBIDE_ROOT"
|
||||
chmod 775 "$WEBIDE_ROOT"
|
||||
|
||||
echo "**** Installing webide dependencies ****"
|
||||
sudo -u webide npm install
|
||||
|
||||
echo "**** Adding default .bashrc file for webide user ****"
|
||||
cp "$WEBIDE_ROOT/scripts/.bashrc" "$WEBIDE_HOME"
|
||||
|
||||
echo "**** Installing the WebIDE as a service ****"
|
||||
echo "**** (to uninstall service, execute: 'sudo update-rc.d -f adafruit-webide.sh remove') ****"
|
||||
cp "$WEBIDE_ROOT/scripts/adafruit-webide.sh" "/etc/init.d"
|
||||
cd /etc/init.d
|
||||
chmod 755 adafruit-webide.sh
|
||||
|
||||
NODE_PATH=""
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
if [ $ARCH = armhf ]; then
|
||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_hf\/node"
|
||||
chmod +x "$WEBIDE_ROOT/bin/node_hf/node"
|
||||
else
|
||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_sf\/node"
|
||||
chmod +x "$WEBIDE_ROOT/bin/node_sf/node"
|
||||
fi
|
||||
sed -i "s/NODE_PATH/$NODE_PATH/g" adafruit-webide.sh
|
||||
|
||||
update-rc.d adafruit-webide.sh defaults
|
||||
|
||||
#set binaries as executable
|
||||
|
||||
echo "Attempting to force reload date and time from ntp server"
|
||||
/etc/init.d/ntp force-reload
|
||||
|
||||
#Check if port 80 is in use, use 8080 if so.
|
||||
PORT_USED=""
|
||||
if netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".80"' | grep -q "LISTEN"
|
||||
then
|
||||
redis-cli HMSET server port 8090
|
||||
PORT_USED=":8090"
|
||||
echo "**** WARNING: PORT 80 IN USE. FALLING BACK TO 8090. ****"
|
||||
echo "**** TO CHOOSE A DIFFERENT PORT USE THE FOLLOWING COMMAND: ****"
|
||||
echo "**** redis-cli HMSET server port 8090 ****"
|
||||
echo "**** AND RESTART THE SERVER ****"
|
||||
fi
|
||||
# echo "**** Installing the WebIDE as a service ****"
|
||||
# echo "**** (to uninstall service, execute: 'sudo update-rc.d -f adafruit-webide.sh remove') ****"
|
||||
cp "$WEBIDE_ROOT/scripts/adafruit-webide.service" "/etc/systemd/system/adafruit-webide.service"
|
||||
systemctl enable adafruit-webide.service
|
||||
systemctl start adafruit-webide.service
|
||||
|
||||
if $OFFLINE
|
||||
then
|
||||
redis-cli HMSET server offline 1
|
||||
fi
|
||||
|
||||
if $GITHUB
|
||||
then
|
||||
redis-cli HMSET server github 1
|
||||
fi
|
||||
|
||||
service adafruit-webide.sh start
|
||||
|
||||
if grep -q adafruit-webide.sh /etc/restartd.conf
|
||||
then
|
||||
echo "restartd already configured"
|
||||
else
|
||||
echo 'webide "node" "service adafruit-webide.sh restart" ""' >> /etc/restartd.conf
|
||||
fi
|
||||
|
||||
#kill all restartd processes, and restart one
|
||||
pkill -f restartd || true
|
||||
sleep 5s
|
||||
restartd
|
||||
|
||||
echo "**** Starting the server...(please wait) ****"
|
||||
sleep 20s
|
||||
|
||||
echo "**** The Adafruit WebIDE is installed and running! ****"
|
||||
echo "**** Commands: sudo service adafruit-webide.sh {start,stop,restart} ****"
|
||||
echo "**** Navigate to http://$(hostname).local$PORT_USED to use the WebIDE"
|
||||
echo "**** Commands: sudo systemctl {start,stop,restart} adafruit-webide ****"
|
||||
echo "**** Navigate to http://$(hostname).local:8080 to use the WebIDE"
|
||||
#echo "**** To run the editor: ****"
|
||||
#echo "**** cd ~/Adafruit/WebIDE ****"
|
||||
#echo "**** node webide ****"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
cd ~
|
||||
git clone git://github.com/adafruit/Adafruit-WebIDE.git
|
||||
cd Adafruit-WebIDE
|
||||
chmod +x bin/node_hf/node
|
||||
sudo ln -s /home/pi/Adafruit-WebIDE/bin/node_hf/node /usr/bin/node
|
||||
sudo ln -s /home/pi/Adafruit-WebIDE/bin/node_hf/node /usr/lib/node
|
||||
curl -L https://npmjs.org/install.sh | sudo sh
|
||||
npm install
|
||||
cd ..
|
||||
cp -r Adafruit-WebIDE Adafruit-WebIDE-Update
|
||||
cd Adafruit-WebIDE-Update/node_modules
|
||||
rm -rf winston passport-bitbucket socket.io jsDAV connect-redis request connect passport express gitty jade redis validator
|
||||
rm -rf winston socket.io jsDAV connect-redis request connect express gitty jade redis validator
|
||||
|
|
|
|||
|
|
@ -42,4 +42,4 @@ echo "**** libraries installed that we did not uninstall as ****"
|
|||
echo "**** we're not able to determine if other applications are dependent ****"
|
||||
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
||||
echo "**** the following command: ****"
|
||||
echo "**** opkg remove nodejs git avahi-daemon i2c-tools python-smbus libcap2 libcap-bin ****"
|
||||
echo "**** opkg remove nodejs git avahi-daemon i2c-tools python-smbus ****"
|
||||
|
|
|
|||
|
|
@ -3,17 +3,10 @@
|
|||
# curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall.sh | sudo sh
|
||||
|
||||
|
||||
WEBIDE_ROOT="/usr/share/adafruit"
|
||||
WEBIDE_ROOT="/usr/share/adafruit/webide"
|
||||
WEBIDE_HOME="/home/webide"
|
||||
NODE_PATH=""
|
||||
|
||||
echo "**** Removing restartd WebIDE configuration ****"
|
||||
sed -i '/adafruit-webide.sh/ d' /etc/restartd.conf
|
||||
#kill all restartd processes, and restart one
|
||||
pkill -f restartd || true
|
||||
sleep 5s
|
||||
restartd
|
||||
|
||||
echo "**** Removing webide user from sudoers ****"
|
||||
if [ -f "/etc/sudoers.tmp" ]; then
|
||||
rm /etc/sudoers.tmp
|
||||
|
|
@ -26,35 +19,28 @@ if [ "$?" -eq "0" ]; then
|
|||
fi
|
||||
rm /etc/sudoers.tmp
|
||||
|
||||
echo "**** Removing access to port 80 for node ****"
|
||||
NODE_PATH=""
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
if [ $ARCH = armhf ]; then
|
||||
NODE_PATH="/usr/share/adafruit/webide/bin/node_hf/node"
|
||||
else
|
||||
NODE_PATH="/usr/share/adafruit/webide/bin/node_sf/node"
|
||||
fi
|
||||
setcap -r "$NODE_PATH"
|
||||
|
||||
echo "**** Stopping the Adafruit WebIDE ****"
|
||||
service adafruit-webide.sh stop
|
||||
sleep 5s
|
||||
|
||||
echo "**** Removing update-rc.d service ****"
|
||||
update-rc.d -f adafruit-webide.sh remove
|
||||
rm /etc/init.d/adafruit-webide.sh
|
||||
echo "**** Removing systemd service ****"
|
||||
systemctl stop adafruit-webide
|
||||
systemctl disable adafruit-webide
|
||||
rm /etc/systemd/system/adafruit-webide.service
|
||||
systemctl daemon-reload
|
||||
systemctl reset-failed
|
||||
|
||||
echo "**** Removing the WebIDE Folder ****"
|
||||
rm -rf "$WEBIDE_ROOT"
|
||||
shopt -s extglob
|
||||
rm -rf "$WEBIDE_ROOT"/!(repositories)
|
||||
echo "**** Removing webide user ****"
|
||||
userdel -r webide
|
||||
|
||||
echo "**** Removing redis server setting ****"
|
||||
redis-cli del server
|
||||
|
||||
echo "**** The Adafruit WebIDE is now uninstalled! ****"
|
||||
echo "**** Your code and repositories remain at $WEBIDE_ROOT ****"
|
||||
echo "**** During the installation process, there were a few ****"
|
||||
echo "**** libraries installed that we did not uninstall as ****"
|
||||
echo "**** we're not able to determine if other applications are dependent ****"
|
||||
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
||||
echo "**** the following command: ****"
|
||||
echo "**** sudo apt-get remove nodejs npm redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus ****"
|
||||
echo "**** sudo apt-get remove nodejs-legacy yarn git i2c-tools python-smbus ntp libkrb5-dev ****"
|
||||
|
|
|
|||
549
server.js
549
server.js
|
|
@ -1,124 +1,52 @@
|
|||
var express = require('express'),
|
||||
tty = require('tty.js'),
|
||||
session = require('express-session'),
|
||||
bodyParser = require('body-parser'),
|
||||
methodOverride = require('method-override'),
|
||||
cookieParser = require('cookie-parser'),
|
||||
serveStatic = require('serve-static'),
|
||||
morgan = require('morgan'),
|
||||
app = express(),
|
||||
expressWs = require('express-ws')(app),
|
||||
multer = require('multer'),
|
||||
upload = multer({ dest: './uploads' }),
|
||||
util = require('util'),
|
||||
io = require('socket.io'),
|
||||
passport = require('passport'),
|
||||
util = require('util'),
|
||||
BitbucketStrategy = require('passport-bitbucket').Strategy,
|
||||
GitHubStrategy = require('passport-github').Strategy,
|
||||
site = require('./controllers/site'),
|
||||
editor = require('./controllers/editor'),
|
||||
user = require('./controllers/user'),
|
||||
jsDAV = require("jsDAV/lib/jsdav"),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
updater = require('./helpers/updater'),
|
||||
scheduler = require('./helpers/scheduler'),
|
||||
editor_setup = require('./helpers/editor_setup'),
|
||||
git_helper = require('./helpers/git_helper'),
|
||||
exec_helper = require('./helpers/exec_helper'),
|
||||
fs_helper = require('./helpers/fs_helper'),
|
||||
exec_helper = require('./helpers/exec_helper'),
|
||||
request_helper = require('./helpers/request_helper'),
|
||||
debug_helper = require('./helpers/python/debug_helper'),
|
||||
RedisStore = require('connect-redis')(express),
|
||||
redis = require("redis"),
|
||||
client = redis.createClient(),
|
||||
config = require('./config/config'),
|
||||
winston = require('winston');
|
||||
winston = require('winston'),
|
||||
db = require('./models/webideModel'),
|
||||
pty = require('node-pty');
|
||||
|
||||
var davServer,
|
||||
HOSTNAME,
|
||||
IS_PASSPORT_SETUP = false,
|
||||
REPOSITORY_PATH = path.resolve(__dirname + "/repositories");
|
||||
|
||||
winston.info("REPOSITORY_PATH", REPOSITORY_PATH);
|
||||
|
||||
//exec_helper.spawn_ipython();
|
||||
|
||||
var terminals = {}, logs = {};
|
||||
|
||||
//check for the existence of the logs directory, if it doesn't
|
||||
//exist, create it prior to starting the child process.
|
||||
var exists = path.existsSync(__dirname + '/logs');
|
||||
var exists = fs.existsSync(__dirname + '/logs');
|
||||
if (!exists) {
|
||||
fs.mkdirSync(__dirname + '/logs', 0755);
|
||||
winston.info('created logs folder');
|
||||
}
|
||||
|
||||
winston.add(winston.transports.File, { filename: __dirname + '/logs/output.log', json: false });
|
||||
winston.handleExceptions(new winston.transports.File({ filename: __dirname + '/logs/errors.log', json: false }));
|
||||
winston.remove(winston.transports.Console);
|
||||
|
||||
// Passport session setup.
|
||||
// To support persistent login sessions, Passport needs to be able to
|
||||
// serialize users into and deserialize users out of the session. Typically,
|
||||
// this will be as simple as storing the user ID when serializing, and finding
|
||||
// the user by ID when deserializing. However, since this example does not
|
||||
// have a database of user records, the complete Bitbucket profile is
|
||||
// serialized and deserialized.
|
||||
//winston.add(winston.transports.File, { filename: __dirname + '/logs/output.log', json: false });
|
||||
//winston.handleExceptions(new winston.transports.File({ filename: __dirname + '/logs/errors.log', json: false }));
|
||||
//winston.remove(winston.transports.Console);
|
||||
|
||||
|
||||
// Use the BitbucketStrategy within Passport.
|
||||
// Strategies in passport require a `verify` function, which accept
|
||||
// credentials (in this case, a token, tokenSecret, and Bitbucket profile),
|
||||
// and invoke a callback with a user object.
|
||||
function setup_bitbucket_passport(consumer_key, consumer_secret) {
|
||||
winston.info("http://" + HOSTNAME + "/auth/bitbucket/callback");
|
||||
passport.use(new BitbucketStrategy({
|
||||
consumerKey: consumer_key,
|
||||
consumerSecret: consumer_secret,
|
||||
callbackURL: "http://" + HOSTNAME + "/auth/bitbucket/callback"
|
||||
},
|
||||
function(token, tokenSecret, profile, done) {
|
||||
// asynchronous verification, for effect...
|
||||
process.nextTick(function () {
|
||||
profile.token = token;
|
||||
profile.token_secret = tokenSecret;
|
||||
profile.consumer_key = consumer_key;
|
||||
profile.consumer_secret = consumer_secret;
|
||||
|
||||
return done(null, profile);
|
||||
});
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// Use the GitHubStrategy within Passport.
|
||||
// Strategies in passport require a `verify` function, which accept
|
||||
// credentials (in this case, a token, tokenSecret, and Github profile),
|
||||
// and invoke a callback with a user object.
|
||||
function setup_github_passport(consumer_key, consumer_secret) {
|
||||
winston.info("http://" + HOSTNAME + "/auth/github/callback");
|
||||
passport.use(new GitHubStrategy({
|
||||
clientID: consumer_key,
|
||||
clientSecret: consumer_secret,
|
||||
callbackURL: "http://" + HOSTNAME + "/auth/github/callback",
|
||||
userAgent: HOSTNAME
|
||||
},
|
||||
function(accessToken, refreshToken, profile, done) {
|
||||
// asynchronous verification, for effect...
|
||||
process.nextTick(function () {
|
||||
profile.token = accessToken;
|
||||
profile.refresh_token = refreshToken;
|
||||
profile.consumer_key = consumer_key;
|
||||
profile.consumer_secret = consumer_secret;
|
||||
|
||||
return done(null, profile);
|
||||
});
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
passport.serializeUser(function(user, done) {
|
||||
client.set(user.username, JSON.stringify(user));
|
||||
done(null, user.username);
|
||||
});
|
||||
|
||||
passport.deserializeUser(function(obj, done) {
|
||||
client.get(obj, function(err, reply) {
|
||||
done(null, JSON.parse(reply));
|
||||
});
|
||||
});
|
||||
winston.info("REPOSITORY_PATH", REPOSITORY_PATH);
|
||||
|
||||
//redirect anything with /filesystem in the url to the WebDav server.
|
||||
app.use(function(req, res, next) {
|
||||
|
|
@ -130,91 +58,118 @@ app.use(function(req, res, next) {
|
|||
}
|
||||
});
|
||||
|
||||
var sessionStore = new RedisStore();
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'pug');
|
||||
app.set('views', __dirname + '/views');
|
||||
app.use(express.logger());
|
||||
//app.use(express.logger("dev"));
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.use(express.static(__dirname + '/node_modules/tty.js/static'));
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.session({
|
||||
store: sessionStore,
|
||||
//logging
|
||||
app.use(morgan('tiny'));
|
||||
app.use(serveStatic(__dirname + '/public'));
|
||||
app.use(serveStatic(__dirname + '/node_modules/xterm/dist'));
|
||||
app.use(cookieParser());
|
||||
var sessionMiddleware = session({
|
||||
key: 'sid',
|
||||
secret: 'cat nap'
|
||||
}));
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.methodOverride());
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
secret: 'cat nap',
|
||||
resave: true,
|
||||
saveUninitialized: true
|
||||
});
|
||||
app.use(sessionMiddleware);
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({ extended: true }))
|
||||
app.use(methodOverride());
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.locals.session = req.session;
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(app.router);
|
||||
app.get('/', site.index);
|
||||
|
||||
app.use(errorHandler);
|
||||
app.get('/editor', editor.index);
|
||||
app.get('/editor/image', editor.image);
|
||||
|
||||
app.post('/editor/upload', upload.single('obj'), editor.upload_file);
|
||||
|
||||
app.get('/', ensureAuthenticated, site.index);
|
||||
|
||||
app.get('/editor', ensureAuthenticated, editor.index);
|
||||
app.get('/editor/image', ensureAuthenticated, editor.image);
|
||||
app.post('/editor/upload', ensureAuthenticated, editor.upload_file);
|
||||
|
||||
app.post('/create/repository', ensureAuthenticated, editor.create_repository);
|
||||
app.post('/create/repository', editor.create_repository);
|
||||
|
||||
app.get('/setup', user.setup);
|
||||
app.post('/setup', user.submit_setup);
|
||||
app.get('/config', user.config);
|
||||
app.post('/config', user.submit_config);
|
||||
app.get('/set-datetime', user.set_datetime);
|
||||
app.get('/login', ensureOauth, user.login);
|
||||
app.get('/logout', user.logout);
|
||||
|
||||
// GET /auth/bitbucket
|
||||
// Use passport.authenticate() as route middleware to authenticate the
|
||||
// request. The first step in Bitbucket authentication will involve redirecting
|
||||
// the user to bitbucket.org. After authorization, Bitbucket will redirect the user
|
||||
// back to this application at /auth/bitbucket/callback
|
||||
app.get('/auth/bitbucket',
|
||||
passport.authenticate('bitbucket'),
|
||||
function(req, res){
|
||||
// The request will be redirected to Bitbucket for authentication, so this
|
||||
// function will not be called.
|
||||
});
|
||||
app.post('/terminals', function (req, res) {
|
||||
var cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
cwd = req.query.cwd;
|
||||
|
||||
// GET /auth/bitbucket/callback
|
||||
// Use passport.authenticate() as route middleware to authenticate the
|
||||
// request. If authentication fails, the user will be redirected back to the
|
||||
// login page. Otherwise, the primary route function function will be calsled,
|
||||
// which, in this example, will redirect the user to the home page.
|
||||
app.get('/auth/bitbucket/callback',
|
||||
passport.authenticate('bitbucket', { failureRedirect: '/login' }),
|
||||
function(req, res) {
|
||||
res.redirect('/editor');
|
||||
});
|
||||
var term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
|
||||
name: 'xterm-color',
|
||||
cols: cols || 80,
|
||||
rows: rows || 24,
|
||||
cwd: path.resolve(cwd),
|
||||
env: process.env
|
||||
});
|
||||
|
||||
// GET /auth/github
|
||||
app.get('/auth/github',
|
||||
passport.authenticate('github'),
|
||||
function(req, res){
|
||||
// The request will be redirected to Github for authentication, so this
|
||||
// function will not be called.
|
||||
console.log('Created terminal with PID: ' + term.pid);
|
||||
terminals[term.pid] = term;
|
||||
logs[term.pid] = '';
|
||||
term.on('data', function(data) {
|
||||
logs[term.pid] += data;
|
||||
});
|
||||
res.send(term.pid.toString());
|
||||
res.end();
|
||||
});
|
||||
|
||||
// GET /auth/github/callback
|
||||
app.get('/auth/github/callback',
|
||||
passport.authenticate('github', { failureRedirect: '/login' }),
|
||||
function(req, res) {
|
||||
res.redirect('/editor');
|
||||
app.post('/terminals/:pid/size', function (req, res) {
|
||||
var pid = parseInt(req.params.pid),
|
||||
cols = parseInt(req.query.cols),
|
||||
rows = parseInt(req.query.rows),
|
||||
term = terminals[pid];
|
||||
|
||||
term.resize(cols, rows);
|
||||
console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
|
||||
res.end();
|
||||
});
|
||||
|
||||
app.ws('/terminals/:pid', function (ws, req) {
|
||||
var term = terminals[parseInt(req.params.pid)];
|
||||
console.log('Connected to terminal ' + term.pid);
|
||||
ws.send(logs[term.pid]);
|
||||
|
||||
term.on('data', function(data) {
|
||||
try {
|
||||
ws.send(data);
|
||||
} catch (ex) {
|
||||
// The WebSocket is not open, ignore
|
||||
}
|
||||
});
|
||||
ws.on('message', function(msg) {
|
||||
try {
|
||||
msg = JSON.parse(msg);
|
||||
} catch (e) {
|
||||
//not json, just a string...
|
||||
}
|
||||
|
||||
if (msg.type === 'input') {
|
||||
term.write(msg.data.toString() + '\r');
|
||||
} else {
|
||||
term.write(msg.toString());
|
||||
}
|
||||
});
|
||||
ws.on('close', function () {
|
||||
term.kill();
|
||||
console.log('Closed terminal ' + term.pid);
|
||||
// Clean things up
|
||||
delete terminals[term.pid];
|
||||
delete logs[term.pid];
|
||||
});
|
||||
});
|
||||
|
||||
app.ws('/editor', editor.editor);
|
||||
|
||||
app.use(errorHandler);
|
||||
|
||||
serverInitialization(app);
|
||||
|
||||
|
||||
function errorHandler(err, req, res, next) {
|
||||
winston.error(err);
|
||||
if (err.name === "InternalOAuthError") {
|
||||
|
|
@ -226,93 +181,6 @@ function errorHandler(err, req, res, next) {
|
|||
}
|
||||
}
|
||||
|
||||
// Simple route middleware to ensure user is authenticated.
|
||||
// Use this route middleware on any resource that needs to be protected. If
|
||||
// the request is authenticated (typically via a persistent login session),
|
||||
// the request will proceed. Otherwise, the user will be redirected to the
|
||||
// login page.
|
||||
function ensureAuthenticated(req, res, next) {
|
||||
setHostName(req);
|
||||
|
||||
if (config.editor.offline) {
|
||||
req.user = { provider: 'offline',
|
||||
username: 'offline user' };
|
||||
return next();
|
||||
}
|
||||
|
||||
function authRoute(req, res, next) {
|
||||
if (req.isAuthenticated()) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (!IS_PASSPORT_SETUP) {
|
||||
res.redirect('/setup');
|
||||
} else {
|
||||
res.redirect('/login');
|
||||
}
|
||||
}
|
||||
|
||||
//use the correct key for redis, either github or bitbucket
|
||||
var oauth_key = 'bitbucket_oauth';
|
||||
if (config.editor.github) {
|
||||
oauth_key = 'github_oauth';
|
||||
}
|
||||
|
||||
if (!IS_PASSPORT_SETUP) {
|
||||
//need to setup passport on server startup, if the oauth is already setup
|
||||
client.hgetall(oauth_key, function (err, oauth) {
|
||||
if (oauth) {
|
||||
if (config.editor.github) {
|
||||
setup_github_passport(oauth.consumer_key, oauth.consumer_secret);
|
||||
} else {
|
||||
setup_bitbucket_passport(oauth.consumer_key, oauth.consumer_secret);
|
||||
}
|
||||
IS_PASSPORT_SETUP = true;
|
||||
|
||||
}
|
||||
authRoute(req, res, next);
|
||||
});
|
||||
} else {
|
||||
authRoute(req, res, next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ensureOauth(req, res, next) {
|
||||
setHostName(req);
|
||||
|
||||
if (config.editor.offline) {
|
||||
req.user = { provider: 'offline',
|
||||
username: 'offline user' };
|
||||
return next();
|
||||
}
|
||||
|
||||
//use the correct key for redis, either github or bitbucket
|
||||
var oauth_key = 'bitbucket_oauth';
|
||||
if (config.editor.github) {
|
||||
oauth_key = 'github_oauth';
|
||||
}
|
||||
|
||||
client.hgetall(oauth_key, function (err, oauth) {
|
||||
if (!oauth) {
|
||||
res.redirect('/setup');
|
||||
} else {
|
||||
if (config.editor.github) {
|
||||
setup_github_passport(oauth.consumer_key, oauth.consumer_secret);
|
||||
} else {
|
||||
setup_bitbucket_passport(oauth.consumer_key, oauth.consumer_secret);
|
||||
}
|
||||
|
||||
if (!IS_PASSPORT_SETUP) {
|
||||
IS_PASSPORT_SETUP = true;
|
||||
res.redirect('/login');
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setHostName(req) {
|
||||
//set it each time, it's quick, and hostname may change (internal IP vs external IP).
|
||||
HOSTNAME = req.headers.host;
|
||||
|
|
@ -321,18 +189,18 @@ function setHostName(req) {
|
|||
function serverInitialization(app) {
|
||||
|
||||
//setup repositories path
|
||||
var exists = path.existsSync(REPOSITORY_PATH);
|
||||
var exists = fs.existsSync(REPOSITORY_PATH);
|
||||
if (!exists) {
|
||||
fs.mkdirSync(REPOSITORY_PATH, 0777);
|
||||
winston.info('created repositories folder');
|
||||
}
|
||||
|
||||
//setup symlink to webide home, if it exists:
|
||||
var has_webide_path = path.existsSync("/home/webide");
|
||||
var has_webide_path = fs.existsSync("/home/webide");
|
||||
if (has_webide_path) {
|
||||
//Creating symbolic link to repositories path
|
||||
winston.info('Linked repository paths: /home/webide/repositories');
|
||||
if (!path.existsSync("/home/webide/repositories")) {
|
||||
if (!fs.existsSync("/home/webide/repositories")) {
|
||||
fs.symlinkSync(REPOSITORY_PATH, "/home/webide/repositories", 'dir');
|
||||
}
|
||||
}
|
||||
|
|
@ -340,189 +208,31 @@ function serverInitialization(app) {
|
|||
scheduler.initialize_jobs();
|
||||
|
||||
start_server(function(server) {
|
||||
socket_listeners();
|
||||
mount_dav(server);
|
||||
});
|
||||
}
|
||||
|
||||
function start_server(cb) {
|
||||
server = require('http').createServer(app);
|
||||
io = io.listen(server);
|
||||
io.configure(function() {
|
||||
io.enable('browser client minification');
|
||||
io.enable('browser client etag');
|
||||
io.set('transports', ['websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling']);
|
||||
});
|
||||
|
||||
new tty.Server(config.term, app, server, io);
|
||||
|
||||
client.hgetall('server', function (err, server_data) {
|
||||
db.find('server', function (err, server_data) {
|
||||
var port;
|
||||
|
||||
if (server_data && server_data.port) {
|
||||
port = server_data.port;
|
||||
} else if (process.env.PORT) {
|
||||
port = process.env.PORT
|
||||
} else {
|
||||
port = config.editor.port;
|
||||
}
|
||||
|
||||
if (server_data && server_data.offline) {
|
||||
config.editor.offline = (server_data.offline == 1) ? true : false;
|
||||
}
|
||||
|
||||
if (server_data && server_data.github) {
|
||||
config.editor.github = (server_data.github == 1) ? true : false;
|
||||
}
|
||||
|
||||
winston.info('listening on port ' + port);
|
||||
cb(server.listen(port));
|
||||
cb(app.listen(port));
|
||||
});
|
||||
}
|
||||
|
||||
function socket_listeners() {
|
||||
io.sockets.authorization(function(handshakeData, callback) {
|
||||
if (!handshakeData.headers.cookie) return callback('socket.io: cookie not found.', false);
|
||||
var signedCookies = require('express/node_modules/cookie').parse(handshakeData.headers.cookie);
|
||||
handshakeData.cookies = require('connect/lib/utils').parseSignedCookies(signedCookies, 'cat nap');
|
||||
|
||||
sessionStore.get(handshakeData.cookies['sid'], function(err, session) {
|
||||
if (config.editor.offline) {
|
||||
handshakeData.session = { provider: 'offline', username: 'offline user' };
|
||||
return callback(null, true);
|
||||
} else {
|
||||
client.get(session.passport.user, function(err, user) {
|
||||
if (err || !session) return callback('socket.io: session not found.', false);
|
||||
handshakeData.session = JSON.parse(user);
|
||||
if (handshakeData.session) {
|
||||
return callback(null, true);
|
||||
} else {
|
||||
return callback('socket.io: session user not found', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.set('username', socket.handshake.session.username);
|
||||
|
||||
//emit on first connection
|
||||
socket.emit('cwd-init', {dirname: REPOSITORY_PATH});
|
||||
scheduler.emit_scheduled_jobs(socket.handshake.session.username, socket);
|
||||
|
||||
socket.on('disconnect', function() {
|
||||
debug_helper.client_disconnect();
|
||||
debug_helper.kill_debug();
|
||||
});
|
||||
|
||||
//listen for events
|
||||
socket.on('git-delete', function(data) {
|
||||
git_helper.remove_commit_push(data.file, socket.handshake.session, function(err, status) {
|
||||
socket.emit('git-delete-complete', {err: err, status: status});
|
||||
});
|
||||
});
|
||||
|
||||
//listen for events
|
||||
socket.on('git-pull', function(data) {
|
||||
console.log(data);
|
||||
var name = data.file ? data.file.name : "";
|
||||
git_helper.pull(name, "origin", "master", function(err, status) {
|
||||
socket.emit('git-pull-complete', {err: err, status: status});
|
||||
});
|
||||
});
|
||||
|
||||
//listen for events
|
||||
socket.on('git-is-modified', function(data) {
|
||||
git_helper.is_modified(data.file, function(err, status) {
|
||||
socket.emit('git-is-modified-complete', {is_modified: status});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('commit-file', function (data) {
|
||||
var commit_message = "";
|
||||
|
||||
if (data.message) {
|
||||
commit_message = data.message;
|
||||
} else {
|
||||
commit_message = "Modified " + data.file.name;
|
||||
}
|
||||
|
||||
git_helper.commit_push_and_save(data.file, commit_message, socket.handshake.session, function(err, status) {
|
||||
socket.emit('commit-file-complete', {err: err, status: status});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('move-file', function (data) {
|
||||
git_helper.move_commit_push(data.file, socket.handshake.session, function(err) {
|
||||
console.log('move-file', err);
|
||||
socket.emit('move-file-complete', {err: err});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('self-check-request', function() {
|
||||
editor_setup.health_check(socket, socket.handshake.session);
|
||||
});
|
||||
|
||||
socket.on('editor-check-updates', function() {
|
||||
updater.check_for_updates(socket);
|
||||
});
|
||||
|
||||
socket.on('editor-update', function() {
|
||||
updater.update(socket);
|
||||
});
|
||||
|
||||
socket.on('trace-file', function(data) {
|
||||
exec_helper.trace_program(data.file, socket);
|
||||
});
|
||||
|
||||
socket.on('debug-command', function(data) {
|
||||
debug_helper.debug_command(data, socket);
|
||||
});
|
||||
|
||||
socket.on('debug-file', function(data) {
|
||||
debug_helper.start_debug(data.file, socket);
|
||||
});
|
||||
|
||||
socket.on('commit-run-file', function(data) {
|
||||
if (data && data.file) {
|
||||
data.file.username = socket.handshake.session.username;
|
||||
}
|
||||
|
||||
exec_helper.execute_program(data.file, false);
|
||||
git_helper.commit_push_and_save(data.file, "Modified " + data.file.name, socket.handshake.session, function(err, status) {
|
||||
socket.emit('commit-file-complete', {message: "Save was successful"});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('stop-script-execution', function(data) {
|
||||
exec_helper.stop_program(data.file, false);
|
||||
});
|
||||
|
||||
socket.on('submit-schedule', function(schedule) {
|
||||
scheduler.add_schedule(schedule, socket, socket.handshake.session);
|
||||
});
|
||||
|
||||
socket.on('schedule-delete-job', function(key) {
|
||||
scheduler.delete_job(key, socket, socket.handshake.session);
|
||||
});
|
||||
|
||||
socket.on('schedule-toggle-job', function(key) {
|
||||
scheduler.toggle_job(key, socket, socket.handshake.session);
|
||||
});
|
||||
|
||||
socket.on('set-settings', function(value) {
|
||||
client.hmset("editor:settings", value, function(err) {
|
||||
if (err) winston.error(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
io.sockets.on('disconnect', function(socket) {
|
||||
exec_helper.set_sockets(io.sockets.sockets);
|
||||
});
|
||||
|
||||
function mount_dav(server) {
|
||||
var jsDAV_Tree_Filesystem = require("jsDAV/lib/DAV/tree/filesystem").jsDAV_Tree_Filesystem;
|
||||
var jsDAV_FS_Tree = require("jsDAV/lib/DAV/backends/fs/tree");
|
||||
//jsDAV.debugMode = true;
|
||||
davServer = jsDAV.mount({
|
||||
path: REPOSITORY_PATH,
|
||||
|
|
@ -530,32 +240,33 @@ function mount_dav(server) {
|
|||
plugins: ["codesearch", "tree", "filelist", "filesearch", "locks", "mount", "temporaryfilefilter"],
|
||||
server: server,
|
||||
standalone: false,
|
||||
tree: new jsDAV_Tree_Filesystem(REPOSITORY_PATH)
|
||||
tree: jsDAV_FS_Tree.new(REPOSITORY_PATH)
|
||||
});
|
||||
winston.info('webdav filesystem mounted');
|
||||
}
|
||||
|
||||
exports.get_socket = function (username, cb) {
|
||||
for (var socketId in io.sockets.sockets) {
|
||||
io.sockets.sockets[socketId].get('username', function(err, sock_username) {
|
||||
if (username === sock_username) {
|
||||
cb(io.sockets.sockets[socketId]);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
function cleanup() {
|
||||
winston.info("process and worker cleanup");
|
||||
Object.keys(terminals).forEach(function (pid) {
|
||||
var term = terminals[pid];
|
||||
console.log('Closed terminal ' + term.pid);
|
||||
term.kill();
|
||||
});
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
winston.info("\nShutting down from SIGINT");
|
||||
// some other closing procedures go here
|
||||
debug_helper.kill_debug(false, function() {
|
||||
//no need to wait for this
|
||||
});
|
||||
}
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
winston.info("Shutting down from SIGINT");
|
||||
cleanup();
|
||||
process.exit();
|
||||
});
|
||||
|
||||
process.on('uncaughtException', function(err) {
|
||||
debug_helper.kill_debug(false, function() {
|
||||
//no need to wait for this
|
||||
});
|
||||
winston.error("Shutting down from uncaughtException");
|
||||
winston.error(err.stack);
|
||||
cleanup();
|
||||
process.exit();
|
||||
});
|
||||
|
|
|
|||
3
uploads/.gitignore
vendored
Normal file
3
uploads/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
*
|
||||
*/
|
||||
!.gitignore
|
||||
|
|
@ -7,7 +7,7 @@ block content
|
|||
#navigator
|
||||
if profile
|
||||
input(type="hidden", name="username", value="#{profile.username}")
|
||||
|
||||
|
||||
#navigator-top
|
||||
p
|
||||
#navigator-folder
|
||||
|
|
@ -28,21 +28,21 @@ block content
|
|||
form(method="post", action="/editor/settings")
|
||||
.settings-element
|
||||
span Select Font Size (px):
|
||||
span.font-size-value.10px 10
|
||||
span.font-size-value.12px 12
|
||||
span.font-size-value.14px 14
|
||||
span.font-size-value.16px 16
|
||||
span.font-size-value.20px 20
|
||||
span.font-size-value._10px 10
|
||||
span.font-size-value._12px 12
|
||||
span.font-size-value._14px 14
|
||||
span.font-size-value._16px 16
|
||||
span.font-size-value._20px 20
|
||||
.settings-element
|
||||
span Use Soft Tabs:
|
||||
span.soft-tab-value.on On
|
||||
span.soft-tab-value.off Off
|
||||
.settings-element
|
||||
span Tab Size:
|
||||
span.tab-size-value.2-value 2
|
||||
span.tab-size-value.4-value 4
|
||||
span.tab-size-value.6-value 6
|
||||
span.tab-size-value.8-value 8
|
||||
span.tab-size-value._2-value 2
|
||||
span.tab-size-value._4-value 4
|
||||
span.tab-size-value._6-value 6
|
||||
span.tab-size-value._8-value 8
|
||||
.settings-element
|
||||
span Show Invisibles:
|
||||
span.invisibles-value.on On
|
||||
|
|
@ -51,6 +51,10 @@ block content
|
|||
span Manual Git commit and push (advanced)
|
||||
span.manual-git-value.on On
|
||||
span.manual-git-value.off Off
|
||||
.settings-element
|
||||
span Python Version:
|
||||
span.python-version._2 2
|
||||
span.python-version._3 3
|
||||
#editor
|
||||
#editor-output-wrapper
|
||||
.dragbar
|
||||
|
|
@ -64,7 +68,7 @@ block content
|
|||
pre
|
||||
.navbar.navbar-fixed-bottom.navbar-inverse
|
||||
.navbar-inner
|
||||
div.editor-version Adafruit WebIDE v#{version} /
|
||||
div.editor-version Adafruit WebIDE v#{version} /
|
||||
a(href="https://github.com/adafruit/Adafruit-WebIDE/issues", class="", target="_blank") Report Bug
|
||||
div.schedule-footer
|
||||
span.schedule-status Scheduler Active
|
||||
|
|
@ -75,10 +79,10 @@ block content
|
|||
.modal-footer
|
||||
button.btn.btn-primary.modal-yes Save Files
|
||||
button.btn.btn-danger.modal-no Don't Save
|
||||
button.btn.modal-cancel Cancel
|
||||
button.btn.modal-cancel Cancel
|
||||
#manual-git-modal(class="modal hide fade")
|
||||
.modal-header
|
||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
||||
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||
h3#create-modal-label Git Commit and Push
|
||||
.modal-body
|
||||
p Add a comment to your edited filed, and click Commit and Push.
|
||||
|
|
@ -87,24 +91,24 @@ block content
|
|||
input(type="text", name="comment", value="")
|
||||
.modal-footer
|
||||
button.btn(data-dismiss="modal", aria-hidden="true") Close
|
||||
button.btn.btn-primary.modal-submit Commit and Push
|
||||
button.btn.btn-primary.modal-submit Commit and Push
|
||||
#create-modal(class="modal hide fade")
|
||||
.modal-header
|
||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
||||
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||
h3#create-modal-label
|
||||
.modal-body
|
||||
p
|
||||
p
|
||||
.modal-footer
|
||||
button.btn(data-dismiss="modal", aria-hidden="true") Close
|
||||
button.btn.btn-primary.modal-submit Save
|
||||
#schedule-modal(class="modal hide fade")
|
||||
.modal-header
|
||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
||||
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||
h3#create-modal-label Job Scheduler
|
||||
.modal-body
|
||||
p Schedule your script to run at specific time periods. There are many combinations you can use to schedule.
|
||||
| For example, by typing "every 5 minutes" into the input, your script will run every 5 minutes until you tell
|
||||
| it to stop.
|
||||
| it to stop.
|
||||
p You can click a few of the pre-set combinations we've provided to give you an idea of the flexibility
|
||||
| of the parser.
|
||||
div.scheduler-error
|
||||
|
|
@ -121,48 +125,25 @@ block content
|
|||
a(href="", class="btn btn-small") every 2 weeks of the year
|
||||
a(href="", class="btn btn-small") on tuesday at 11:00 am
|
||||
a(href="", class="btn btn-small") on the 1st day of the month
|
||||
a(href="", class="btn btn-small") on the 15,18,20 minute
|
||||
a(href="", class="btn btn-small") on the 15,18,20 minute
|
||||
.modal-footer
|
||||
button.btn(data-dismiss="modal", aria-hidden="true") Close
|
||||
button.btn.btn-primary.modal-submit Submit
|
||||
#notification-modal(class="modal hide fade")
|
||||
.modal-header
|
||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
||||
h3#create-modal-label WebIDE Message
|
||||
.modal-body
|
||||
p Please ensure your repositories are listed private or public at Bitbucket based on your preferences.
|
||||
p You can validate them by viewing your <a href="https://bitbucket.org" target="_blank">bitbucket profile page</a>
|
||||
| , and looking for the padlock to the left of the repository
|
||||
| name in the "Repositories" sidebar.
|
||||
p To make the repository private or public, click the repository name, and then the gear in the header on the
|
||||
| the repository page. Then click the checkbox in the form to make the repository private or public,
|
||||
| and click submit.
|
||||
p This particular notification will only display one time. Thank you!
|
||||
.modal-footer
|
||||
button.btn(data-dismiss="modal", aria-hidden="true") Dismiss
|
||||
script(type="text/javascript")
|
||||
if(!#{shown_notification}) {
|
||||
setTimeout(function() {
|
||||
$('#notification-modal').modal({show: true, backdrop: 'static'});
|
||||
}, 20000);
|
||||
|
||||
}
|
||||
button.btn.btn-primary.modal-submit Submit
|
||||
script(src="/javascripts/ace/ace.js")
|
||||
script(src="/socket.io/socket.io.js")
|
||||
script(src="/term.js")
|
||||
script(src="/options.js")
|
||||
script(src="/tty.js")
|
||||
script(src="/javascripts/trace/d3.v2.min.js")
|
||||
script(src="/javascripts/trace/jquery.ba-bbq.min.js")
|
||||
script(src="/javascripts/trace/jquery.jsPlumb-1.3.10-all-min.js")
|
||||
script(src="/javascripts/trace/pytutor.js")
|
||||
script(src="/javascripts/trace/pytutor.js")
|
||||
script(src="/javascripts/fileupload/js/vendor/jquery.ui.widget.js")
|
||||
script(src="/javascripts/fileupload/js/jquery.fileupload.js")
|
||||
script(src="/javascripts/fileupload/js/jquery.fileupload-ui.js")
|
||||
script(src="/javascripts/fileupload/js/jquery.fileupload-ui.js")
|
||||
script(src="/javascripts/davFS.js")
|
||||
script(src="/xterm.js")
|
||||
script(src="/addons/fit/fit.js")
|
||||
script(src="/addons/attach/attach.js")
|
||||
script(src="/javascripts/later/later-recur.min.js")
|
||||
script(src="/javascripts/later/later.min.js")
|
||||
script(src="/javascripts/jquery.colorbox-min.js")
|
||||
script(src="/javascripts/context_menu.js")
|
||||
script(src="/javascripts/webide_utils.js")
|
||||
script(src="/javascripts/occ_editor.js")
|
||||
script(src="/javascripts/editor.js")
|
||||
|
|
@ -3,7 +3,6 @@ extends layout
|
|||
block content
|
||||
#login-wrapper
|
||||
#login-content
|
||||
p There was an error with your request. Please try again, or visit
|
||||
p There was an error with your request. Please try again, or visit
|
||||
a(href="http://learn.adafruit.com/webide/faq") the FAQ for assistance
|
||||
| .
|
||||
p #{error}
|
||||
p #{error}
|
||||
|
|
@ -6,6 +6,6 @@ head
|
|||
link(rel="stylesheet", href="/javascripts/fileupload/css/jquery.fileupload-ui.css")
|
||||
link(rel="stylesheet", href="/stylesheets/colorbox.css")
|
||||
link(rel="stylesheet", href="/stylesheets/app.css")
|
||||
link(rel="stylesheet", href="/style.css")
|
||||
link(rel="stylesheet", href="/xterm.css")
|
||||
link(rel="stylesheet", href="/stylesheets/pytutor.css")
|
||||
script(src='/javascripts/jquery.min.js')
|
||||
script(src='/javascripts/jquery.min.js')
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
- if (!user)
|
||||
h4 Welcome! Please log in.
|
||||
a(href="/auth/bitbucket") Login with Bitbucket
|
||||
- else
|
||||
h4 Hello, #{user.username}
|
||||
p Please choose a repository
|
||||
for repository in user._json.repositories
|
||||
.repository
|
||||
a(href="/editor/#{repository.name}") #{repository.name}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
!!! 5
|
||||
html
|
||||
include header
|
||||
body
|
||||
|
|
@ -7,12 +6,9 @@ html
|
|||
.container-fluid
|
||||
a.brand(href="/")
|
||||
img(src="/images/WebIDE_Logo_Beta@2x.png", style="height:30px;")
|
||||
p.logout-wrapper
|
||||
- if (typeof profile !== "undefined")
|
||||
a(href="/logout") Log out
|
||||
p.update-wrapper
|
||||
div.connection-state
|
||||
|
||||
#container
|
||||
block content
|
||||
script(src='/javascripts/bootstrap.min.js')
|
||||
script(src='/javascripts/bootstrap.min.js')
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
#login-wrapper
|
||||
#login-content
|
||||
p There was an error signing in. It could be any number of reasons, but first ensure that your date/time is set accurately on your Pi.
|
||||
| For More help, visit
|
||||
a(href="http://learn.adafruit.com/webide/faq") the FAQ for assistance
|
||||
| .
|
||||
p To try and repair the error, by setting your date and time, click the below link. You will be redirected to the login page after 5-10 seconds to try login in again.
|
||||
p
|
||||
a(href="/set-datetime") Set the Date and Time
|
||||
p #{error}
|
||||
|
|
@ -11,7 +11,7 @@ block content
|
|||
| of your Pi here. You can also configure the Wifi settings. Both of these
|
||||
| features are optional, and may be skipped.
|
||||
p If you leave these fields blank, they will not overwrite your existing settings.
|
||||
p You can update these settings at any time in the future.
|
||||
p You can update these settings at any time in the future.
|
||||
p Change your Pi Hostname (optional)
|
||||
form(method="post", action="/config", class="form-horizontal")
|
||||
div.control-group
|
||||
|
|
@ -22,7 +22,7 @@ block content
|
|||
div.control-group
|
||||
label(for="port", class="control-label") Port:
|
||||
div.controls
|
||||
input(type="text", name="port", value=port, autocomplete="off")
|
||||
input(type="text", name="port", value=port, autocomplete="off")
|
||||
p Configure your WIFI settings (optional)
|
||||
div.control-group
|
||||
label(for="wifi_ssid", class="control-label") WiFi SSID:
|
||||
|
|
@ -35,4 +35,4 @@ block content
|
|||
p
|
||||
input(type="submit", class="btn btn-primarybtn-large", name="Submit")
|
||||
p Note: It's not recommended to change these settings while accessing the Pi through an external
|
||||
| network, as the connection is not secure.
|
||||
| network, as the connection is not secure.
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
extends ../layout
|
||||
|
||||
block content
|
||||
#login-wrapper
|
||||
#login-content
|
||||
if (typeof(session.message) != 'undefined')
|
||||
div.login-info
|
||||
div.alert.alert-info
|
||||
p #{session.message}
|
||||
#{session.message = undefined}
|
||||
if !github
|
||||
img(src="/images/login/login2_logos.jpg")
|
||||
if github
|
||||
a(href="/auth/github", rel="external", class="btn btn-large") Click here to log in to your Github Account
|
||||
else
|
||||
a(href="/auth/bitbucket", rel="external", class="btn btn-large") Click here to log in to your Bitbucket Account
|
||||
.login-help
|
||||
b Need Help?
|
||||
a(href="http://learn.adafruit.com/webide", target="_blank") Learn how to use the Adafruit webIDE here.
|
||||
0
views/users/repositories.pug
Normal file
0
views/users/repositories.pug
Normal file
|
|
@ -1,59 +0,0 @@
|
|||
extends ../layout
|
||||
|
||||
block content
|
||||
#setup-wrapper
|
||||
#setup-content
|
||||
h3 Welcome to the Adafruit webIDE powered by the Adafruit Learning System
|
||||
if (typeof(session.message) != 'undefined')
|
||||
div.alert.alert-error
|
||||
p #{session.message}
|
||||
p Setting up your Raspberry Pi or Beaglebone will only take a few minutes. Let's get started.
|
||||
p Are you setting up more than one Raspberry Pi or Beaglebone? Visit the config to
|
||||
a(href="/config") change hostname and WiFi.
|
||||
if !github
|
||||
p One of the many useful features of the webIDE is that all of your code will be
|
||||
| stored in the cloud over at bitbucket.org. So, before we can go any further, you
|
||||
| will want to create your free Bitbucket account. If you already have one, you can use
|
||||
| your existing account, or create one specifically for the webIDE.
|
||||
p
|
||||
a.btn.btn-large.btn-info.bitbucket-signup(href="https://bitbucket.org/account/signup/", target="_blank") Click here to create your free bitbucket account
|
||||
p
|
||||
img(src="/images/setup/step1.png")
|
||||
p In your Account page, click on the Integrated Applications link in the left column:
|
||||
p
|
||||
img(src="/images/setup/step2.png")
|
||||
p Now, click on the '+ Add consumer' button:
|
||||
p
|
||||
img(src="/images/setup/step3.png")
|
||||
p For the name, type in Adafruit webIDE, then click the 'Add consumer' button:
|
||||
p
|
||||
img(src="/images/setup/step4.png")
|
||||
p What we are after is the Key, and the Secret text. Copy each of those and paste in the boxes below.
|
||||
p
|
||||
img(src="/images/setup/step5.png")
|
||||
p Copy the key and Secret codes into these text boxes, and then click submit:
|
||||
if github
|
||||
p Enter your Github OAuth Consumer Key and Secret here:
|
||||
form(method="post", action="/setup", class="form-horizontal")
|
||||
div.control-group
|
||||
label(for="key", class="control-label") Key:
|
||||
div.controls
|
||||
input(type="text", name="key", value=consumer_key)
|
||||
div.control-group
|
||||
label(for="secret", class="control-label") Secret:
|
||||
div.controls
|
||||
input(type="text", name="secret", value=consumer_secret)
|
||||
if github
|
||||
p Add your Full Name and Email to attach to saved files at Github (git config)
|
||||
else
|
||||
p Add your Full Name and Email to attach to saved files at Bitbucket (git config)
|
||||
div.control-group
|
||||
label(for="name", class="control-label") Full Name:
|
||||
div.controls
|
||||
input(type="text", name="name", value=name)
|
||||
div.control-group
|
||||
label(for="email", class="control-label") Email:
|
||||
div.controls
|
||||
input(type="text", name="email", value=email)
|
||||
p
|
||||
input(type="submit", class="btn btn-primary btn-large", name="Submit")
|
||||
24
views/users/setup.pug
Normal file
24
views/users/setup.pug
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
extends ../layout
|
||||
|
||||
block content
|
||||
#setup-wrapper
|
||||
#setup-content
|
||||
h3 Welcome to the Adafruit webIDE powered by the Adafruit Learning System
|
||||
if (typeof(session.message) != 'undefined')
|
||||
div.alert.alert-error
|
||||
p #{session.message}
|
||||
p Setting up your Raspberry Pi or Beaglebone will only take a few minutes. Let's get started.
|
||||
p Are you setting up more than one Raspberry Pi or Beaglebone? Visit the config to
|
||||
a(href="/config") change hostname and WiFi.
|
||||
form(method="post", action="/setup", class="form-horizontal")
|
||||
p Add your Name and Email for git config
|
||||
div.control-group
|
||||
label(for="name", class="control-label") Full Name:
|
||||
div.controls
|
||||
input(type="text", name="name", value=name)
|
||||
div.control-group
|
||||
label(for="email", class="control-label") Email:
|
||||
div.controls
|
||||
input(type="text", name="email", value=email)
|
||||
p
|
||||
input(type="submit", class="btn btn-primary btn-large", name="Submit")
|
||||
Loading…
Reference in a new issue