UNPKG

tooltwist

Version:
483 lines (401 loc) 13.6 kB
/* * Run the Tooltwist server. * This prepares all the config files, then uses Gradle to do the actual build and run. */ var Log = require('./log'), Git = require('git-wrapper'), Config = require('./config'), Mustache = require("mustache"), Templates = require("./templates"), fs = require('fs'), mkdirp = require('mkdirp'), gradle = require('./gradle'), controller = require('./controller'); // Directory locations // var PROJECT_ROOT = Config.PROJECT_ROOT; //var TTDIR = Config.getHiddenDir(); // var WEBDESIGN_DIR = Config.getHiddenDir() + '/webdesign-projects'; // var EXTENSIONS_DIR = Config.getHiddenDir() + '/extension-projects'; //var RESOURCES_DIR = __dirname + '/..'; /** * Search for the web design project that maps onto a specific repository. */ exports.findWebdesignProject = function(repoUrl, callback) { Log.debug(); Log.debug('server.findWebdesignProject(' + repoUrl + ')') // Check the input parameters /* * Check we have the webdesign project */ /* mkdirp.sync(Config.HIDDEN_DIR); if (project) { // A project is specified, see if it has been downlaoded already var dir = Config.WEBDESIGN_DIR + "/" + project; if (fs.existsSync(dir)) { var stat = fs.statSync(dir); if (stat.isDirectory()) { // We have a project. If we also have a repository, check it is the right one. if (repoUrl) { // Check the repository is the right one. projectIsForRepository(project, repoUrl, function(isForRepo){ if (isForRepo){ // Outcome - project found for specified repo - update project. return doPullRequest(project, callback); } else { // Outcome - project found but does not match repo - error. Log.info("\nError: project '" + project + "' is not for " + repoUrl); return callback(null); } }); } else { // Outcome - project found and no repo specified - update project. return doPullRequest(project, callback); } } else { // Outcome - specified project is not found - error. Log.info("\nError: unknown project '" + project + "'."); return callback(null); } } else { // Specified project does not exist, clone from github if we have a URL if (repoUrl) { // Outcome - specified project missing but repo specified - clone repo. return cloneRepository(repoUrl, project, branch, callback); } else { // Outcome - specified project missing and no repo specified - error. Log.info('\nError: project ' + project + ' not found, and no repository was specified.') return callback(null); } } } else { */ // Project not specified - see if a repository is specified Log.debug('no project specified') if (repoUrl) { // Find the project that uses this repository Log.debug('no project but repo ' + repoUrl) return findProjectForRepository(repoUrl, callback); /*function(project, remote){ if (project == null) { // Outcome - repository specified but not found - clone the repo. //Log.info("No web design project found for repository '" + repoUrl + "'"); return exports.cloneRepository(repoUrl, project, callback); } else { // Outcome - repository specified and found - update the project. return doPullRequest(project, callback); } }); */ } else { // Outcome - no project or repo has been specified - let the user choose one. return chooseProject(callback); /*function(project){ return callback(project); }); */ } /* } */ /** * Prompt the user for which project to use. * If there's only one project, use it. */ function chooseProject(cb) { Log.debug() Log.debug('chooseProject') if ( !fs.existsSync(Config.WEBDESIGN_DIR)) { Log.error("No projects found. Try -r <repositoryUrl> to add a project."); process.exit(1); // return cb(null); } var projects = []; var list = fs.readdirSync(Config.WEBDESIGN_DIR); list.forEach(function (file, index) { var path = Config.WEBDESIGN_DIR + '/' + file + '/project.json'; if (fs.existsSync(path)) { Log.debug(" ---> " + path + ', ' + index); projects.push(file); } }); // Maybe there are no projects. if (projects.length == 0) { Log.debug("NO PROJECTS") return cb(null); } // If there's only one project, use it. if (projects.length == 1) { Log.debug('using the only project') var project = projects[0]; return cb(project); /*doPullRequest(project, cb); */ } // List the available projects Log.always('Please select one of the following projects:') for (var i = 0; i < projects.length; i++) { Log.always(' ' + (i+1) + ': ' + projects[i]); } // Ask the user which project. var rl = require('readline').createInterface(process.stdin, process.stdout); rl.setPrompt('Selection: '); rl.prompt(); rl.on('line', function(line) { var index = parseInt(line); if (index > 0 && index <= projects.length){ Log.debug('index is ' + index) var project = projects[index - 1]; // doPullRequest(project, cb); rl.close(); return callback(project); } else { rl.prompt(); } }); } /** * Find a webdesign project for the specified repository */ function findProjectForRepository(repository, callback) { Log.debug() Log.debug('server.findProjectForRepository(' + repository + ')') Log.debug('Scanning existing webdesign projects for: ' + repository) if ( !fs.existsSync(Config.WEBDESIGN_DIR)) { return callback(null); } // Get a list of the available projects var projects = []; var list = fs.readdirSync(Config.WEBDESIGN_DIR); list.forEach(function (file, index) { var path = Config.WEBDESIGN_DIR + '/' + file + '/.git'; if (fs.existsSync(path)) { // Add this project directory to the list projects.push(file); // Check we have a project.json file var path = Config.WEBDESIGN_DIR + '/' + file + '/project.json'; if ( !fs.existsSync(path)) { Log.warn("WARNING: Missing " + path); } } }); // List the available projects Log.debug('projects: ', projects) findProjectForRepository2(repository, projects, 0, callback); } function findProjectForRepository2(repoUrl, projects, index, callback){ Log.debug('findProjectForRepository2, repoUrl=' + repoUrl + ", index=" + index) if (index >= projects.length) { // Run off the end of the list Log.debug('checked all projects, and not found') Log.debug('Project not found') return callback(null); } var project = projects[index]; Log.debug("Checking remotes for " + project) var path = Config.WEBDESIGN_DIR + '/' + project + '/.git'; //var found = false var git = new Git({ 'git-dir': path }); git.exec('remote', { v: true}, [ ], function(err, msg){ if (err) { Log.error('Error: ', err) process.exit(1); } Log.debug('Message is:\n' + msg) var lines = msg.split('\n'); //Log.debug(" lines=", lines) for (var i = 0; i < lines.length; i++) { var line = lines[i]; //Log.debug(); //Log.debug(" line=", line) if (line === ''){ continue; } var arr = line.split('\t'); if (arr.length != 2) { Log.error('Unrecognized string returned by \'git remote -v\' in ' + path + ':\n' + line); Log.debug('arr=', arr) return callback(null); } if (arr[0] === 'origin' && endsWith(arr[1], ' (fetch)')) { //Log.debug(" arr=", arr) var url = arr[1].substring(0, arr[1].length - 8); Log.debug(' url=' + url + '.') if (url === repoUrl) { var remote = arr[0]; Log.debug('FOUND REPO: ' + project + ', ' + remote) Log.debug('Project \'' + project + '\' is for this repository.\n') return callback(project) } } } // Not this project - try the next project Log.debug('Check next project') findProjectForRepository2(repoUrl, projects, index + 1, callback); }); } }; exports.cloneWebdesignProject = function(repoUrl, branch, callback) { Log.debug() Log.debug('server.cloneWebdesignProject(' + repoUrl + ')') Log.info('Clone git repository ' + repoUrl) // callback(null); if ( !endsWith(repoUrl, '.git')){ Log.error('Error: URL does not end with \'.git\': ' + repoUrl) process.exit(1); } // Get the project name var project = repoUrl.substring(0, repoUrl.length - 4) var pos = project.lastIndexOf('/') if (pos >= 0) project = project.substring(pos + 1) // Do the clone mkdirp.sync(Config.WEBDESIGN_DIR); try { // Do the clone, in the Webdesign directory Log.info('$ cd ' + Config.WEBDESIGN_DIR) Log.info('$ git clone -b ' + branch + ' '+ repoUrl) var initialDirectory = process.cwd(); // remember where are, so we can come back. process.chdir(Config.WEBDESIGN_DIR); var git = new Git({ }); git.exec('clone', { }, [ '-b', branch, repoUrl ], function(err, msg){ if (err) { Log.error('Error: ' + err) process.exit(1); } Log.info(msg) process.chdir(initialDirectory); return callback(project); }); } catch (err) { Log.error('chdir: ' + err); process.exit(1); } } /** * Do a git pull */ exports.pullWebdesignProject = function(project, branch, callback){ Log.debug() Log.debug("server.pullWebdesignProject(" + project + ', ' + branch + ')') Log.info("Update project " + project + ' from git.') var path = Config.WEBDESIGN_DIR + "/" + project + "/.git"; Log.info('$ cd ' + path) // Log.info('$ git stash save --include-untracked') Log.info('$ git pull') // First stash any changes, in case someone wants them later // var git = new Git({ 'git-dir': path }); // git.exec('stash', { }, [ 'save', '--include-untracked' ], function(err, msg){ // if (err) { // Log.error('Error: ' + err) // throw err; // } // Log.info(msg) // Now do the pull var git2 = new Git({ 'git-dir': path }); git2.exec('pull', { }, [ ], function(err, msg){ if (err) { Log.error('Error: ' + err) throw err; } Log.info(msg) Log.info('Update complete.\n') // Check we are on the right branch. return exports.checkBranch(project, branch, callback); }); // }); } /** * Check that the webdesign is on the right branch. If not, don't * try to rectify the problem - inform the user and bomb out. */ exports.checkBranch = function(project, branch, callback){ Log.debug() Log.debug("server.checkBranch(" + project + ', ' + branch + ')') Log.info("Check branch of project " + project) // For some reason, we need to be in the webdesign project // directory, or we get "Error: stdout maxBuffer exceeded." var initialDirectory = process.cwd(); // remember where are, so we can come back. process.chdir(Config.WEBDESIGN_DIR + '/' + project); // Get the branch using 'git status' var path = Config.WEBDESIGN_DIR + "/" + project + "/.git"; Log.info('$ cd ' + path) Log.info('$ git status') var git = new Git({ 'git-dir': path }); git.exec('status', { }, [ ], function(err, msg){ process.chdir(initialDirectory); if (err) { Log.error('Error: ' + err) throw err; } //Log.debug('Status is:\n' + msg) var lines = msg.split('\n'); //Log.debug(" lines=", lines) for (var i = 0; i < lines.length; i++) { var line = lines[i]; var currentBranch = null; if (/^On branch /) { var regexp = /On branch (.*)/; var match = regexp.exec(line); currentBranch = match[1]; break; } } // Check the current branch was found. Log.info('webdesign is on branch \'' + currentBranch + '\'.'); if (currentBranch == null) { // Should not happen Log.error(); Log.error('Error: \'git status\' did not show current branch.'); Log.error(); process.exit(1); } // If we are on the wrong branch, change branch now. if (currentBranch !== branch) { // Get the path to the config file where the branch was defined. var branchDefinitionLocation = Config.PROJECT_ROOT + '/' + Config.CONFIG_FILE; if (Config.getConfig().mode === 'controller') { branchDefinitionLocation = '/ControllerV8/config-files/deploymentConfig.' + Controller.LAUNCHPAD_NAME + '.xml'; } // Display the error message. Log.always(); Log.always('\tPROBLEM:'); Log.always(); Log.always('\tYour webdesign project is currently on the wrong branch. ToolTwist'); Log.always('\tcannot switch branches because it does not know which updates you'); Log.always('\twould like to keep. You will need to switch branches manually.'); Log.always(); Log.always('\tWebdesign directory: ' + (Config.WEBDESIGN_DIR + "/" + project)); Log.always('\tCurrent branch: ' + currentBranch); Log.always('\tBranch specified in config file: ' + branch); Log.always('\t(' + branchDefinitionLocation + ')'); Log.always(); process.exit(1); // // Get the branch using 'git checkout <branch>' // var path = Config.WEBDESIGN_DIR + "/" + project + "/.git"; // // Log.info('$ cd ' + path) // Log.info('$ git checkout ' + branch) // var git = new Git({ 'git-dir': path }); // git.exec('checkout', { }, [ branch ], function(err, msg){ // // // Check the rply // if (err) { // Log.error('Error: ' + err) // throw err; // } // Log.info(msg) // process.exit(1); // return callback(project); // }); } // All good. Carry on. return callback(project); }); } /** * See if a string ends with a particular suffix. */ function endsWith(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; }