<commit_before>require.paths.unshift(__dirname + '/lib/node');

var express = require('express'),
    fs = require('fs'),
    path = require('path'),
    rmrf = require('./rm-rf'),
    events = require('events'),
    _ = require('underscore')._;

var settings = require('./settings');
var app = module.exports = express.createServer();

app.use(express.bodyDecoder());
app.use(express.methodOverride());
app.use(express.staticProvider('client'));

app.get('/api', function(req, res, params) {
  res.send({
    api: 'basic',
    version: 1.0
  });
});

app.get('/api/project/:projectId?', loadProjects, function(req, res, next) {
    if (req.param('projectId')) {
        res.send(res.projects.pop());
    }
    else {
        res.send(res.projects);
    }
});

app.put('/api/project/:projectId', function(req, res, next) {
    var project = new Project(req.body);
    project.save(function(err) {
        project.load(function(err, project) {
            res.send(project);
        });
    });
});

app.post('/api/project/:projectId', function(req, res, next) {
    var project = new Project(req.body);
    project.save(function(err) {
        project.load(function(err, project) {
            res.send(project);
        });
    });
});

app.del('/api/project/:projectId', loadProjects, function(req, res, next) {
    var project = res.projects.pop();
    project.delete(function() {
        res.send({});
    });
});

/**
 * Project model.
 */
var Project = function(object) {
    this.srs = '';
    this.Stylesheet = [];
    this.Layer = [];
    _.extend(this, object);
};

Project.prototype.load = function(callback) {
    var self = this;
    var projectPath = path.join(settings.files, 'project', this.id);
    fs.readFile(path.join(projectPath, self.id + '.mml'), 'utf-8', function(err, data) {
        if (err || !data) {
            return callback(new Error('Error reading project file.'));
        }
        var object = JSON.parse(data);
        if (data && object) {
            _.extend(self, object);
        }
        if (self.Stylesheet && self.Stylesheet.length > 0) {
            var queue = new events.EventEmitter;
            var queueLength = self.Stylesheet.length;
            _.each(self.Stylesheet, function(filename, key) {
                fs.readFile(path.join(projectPath, filename),
                'utf-8',
                function(err, data) {
                    self.Stylesheet[key] = {id: filename, data: data};
                    queueLength--;
                    if (queueLength === 0) {
                        queue.emit('complete');
                    }
                });
            });
            queue.on('complete', function() {
                callback(null, self);
            });
        }
        else {
            callback(err, self);
        }
    });
};

Project.prototype.save = function(callback) {
    var self = this;
    var projectPath = path.join(settings.files, 'project', this.id);

    rmrf(projectPath, function() {
        fs.mkdir(projectPath, 0777, function() {
            var data = _.extend({}, self);
            var files = [];
            if (data.id) {
                delete data.id;
            }
            if (data.Stylesheet) {
                _.each(data.Stylesheet, function(stylesheet, key) {
                    if (stylesheet.id) {
                        files.push({
                            filename: stylesheet.id,
                            data: stylesheet.data
                        });
                        data.Stylesheet[key] = stylesheet.id;
                    }
                });
            }
            files.push({
                filename: self.id + '.mml',
                data: JSON.stringify(data)
            });

            var queue = new events.EventEmitter;
            var queueLength = files.length;
            for (var i = 0; i < files.length; i++) {
                // @TODO work through stylesheet queue and save each one individually.
                fs.writeFile(path.join(projectPath, files[i].filename), files[i].data, function(err) {
                    queueLength--;
                    if (queueLength === 0) {
                        queue.emit('complete');
                    }
                });
            }
            queue.on('complete', callback);
        });
    });
}

Project.prototype.delete = function(callback) {
    var projectPath = path.join(settings.files, 'project', this.id);
    rmrf(projectPath, callback);
};

function loadProjects(req, res, next) {
    res.projects = [];
    if (req.param('projectId')) {
        var project = new Project({id: req.param('projectId') });
        project.load(function(err, project) {
            if (project) {
                res.projects.push(project);
            }
            next();
        });
    }
    else {
        var queue = new events.EventEmitter;
        var basepath = path.join(settings.files, 'project');
        path.exists(basepath, function(exists) {
            if (!exists) fs.mkdirSync(basepath, 0777);
            fs.readdir(basepath, function(err, projects) {
                if (err) {
                    return next(new Error('Error reading projects directory.'));
                }
                else if (projects.length === 0) {
                    next();<commit_msg>Trickle-up errors<commit_after>require.paths.unshift(__dirname + '/lib/node');

var express = require('express'),
    fs = require('fs'),
    path = require('path'),
    rmrf = require('./rm-rf'),
    events = require('events'),
    _ = require('underscore')._;

var settings = require('./settings');
var app = module.exports = express.createServer();

app.use(express.bodyDecoder());
app.use(express.methodOverride());
app.use(express.staticProvider('client'));

app.get('/api', function(req, res, params) {
  res.send({
    api: 'basic',
    version: 1.0
  });
});

app.get('/api/project/:projectId?', loadProjects, function(req, res, next) {
    if (req.param('projectId')) {
        res.send(res.projects.pop());
    }
    else {
        res.send(res.projects);
    }
});

app.put('/api/project/:projectId', function(req, res, next) {
    var project = new Project(req.body);
    project.save(function(err) {
        project.load(function(err, project) {
            res.send(project);
        });
    });
});

app.post('/api/project/:projectId', function(req, res, next) {
    var project = new Project(req.body);
    project.save(function(err) {
        project.load(function(err, project) {
            res.send(project);
        });
    });
});

app.del('/api/project/:projectId', loadProjects, function(req, res, next) {
    var project = res.projects.pop();
    project.delete(function() {
        res.send({});
    });
});

/**
 * Project model.
 */
var Project = function(object) {
    this.srs = '';
    this.Stylesheet = [];
    this.Layer = [];
    _.extend(this, object);
};

Project.prototype.load = function(callback) {
    var self = this;
    var projectPath = path.join(settings.files, 'project', this.id);
    fs.readFile(path.join(projectPath, self.id + '.mml'),
    'utf-8',
    function(err, data) {
        if (err || !data) {
            return callback(new Error('Error reading project file.'));
        }
        var object = JSON.parse(data);
        if (data && object) {
            _.extend(self, object);
        }
        if (self.Stylesheet && self.Stylesheet.length > 0) {
            var queue = new events.EventEmitter;
            var queueLength = self.Stylesheet.length;
            _.each(self.Stylesheet, function(filename, key) {
                fs.readFile(path.join(projectPath, filename),
                'utf-8',
                function(err, data) {
                    self.Stylesheet[key] = {
                        id: filename,
                        data: data
                    };
                    queueLength--;
                    if (queueLength === 0) {
                        queue.emit('complete');
                    }
                });
            });
            queue.on('complete', function() {
                callback(null, self);
            });
        }
        else {
            callback(err, self);
        }
    });
};

Project.prototype.save = function(callback) {
    var self = this;
    var projectPath = path.join(settings.files, 'project', this.id);

    rmrf(projectPath, function() {
        fs.mkdir(projectPath, 0777, function() {
            var data = _.extend({}, self);
            var files = [];
            if (data.id) {
                delete data.id;
            }
            if (data.Stylesheet) {
                _.each(data.Stylesheet, function(stylesheet, key) {
                    if (stylesheet.id) {
                        files.push({
                            filename: stylesheet.id,
                            data: stylesheet.data
                        });
                        data.Stylesheet[key] = stylesheet.id;
                    }
                });
            }
            files.push({
                filename: self.id + '.mml',
                data: JSON.stringify(data)
            });

            var queue = new events.EventEmitter;
            var queueLength = files.length;
            for (var i = 0; i < files.length; i++) {
                // @TODO work through stylesheet queue and save each one individually.
                fs.writeFile(path.join(projectPath, files[i].filename), files[i].data, function(err) {
                    queueLength--;
                    if (queueLength === 0) {
                        queue.emit('complete');
                    }
                });
            }
            queue.on('complete', callback);
        });
    });
}

Project.prototype.delete = function(callback) {
    var projectPath = path.join(settings.files, 'project', this.id);
    rmrf(projectPath, callback);
};

function loadProjects(req, res, next) {
    res.projects = [];
    if (req.param('projectId')) {
        var project = new Project({id: req.param('projectId') });
        project.load(function(err, project) {
            if (project) {
                res.projects.push(project);
                next();
            }
            else {
                next(err);
            }
        });
    }
    else {
        var queue = new events.EventEmitter;
        var basepath = path.join(settings.files, 'project');
        path.exists(basepath, function(exists) {
            if (!exists) fs.mkdirSync(basepath, 0777);
            fs.readdir(basepath, function(err, projects) {
                if (err) {
                    return next(new Error('Error reading projects directory.'));
                }
                else if (projects.length === 0) {
                    next();
{'fraction_non_alphanumeric': 0.14782447006322053, 'fraction_numerical': 0.0031610264038676086, 'mean_word_length': 1.650160137965016, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2698280', 'n_tokens_mistral': 3026, 'n_tokens_neox': 2952, 'n_words': 590}