tasks/debian_package.js
/*
* grunt-debian-package
* https://github.com/jamesdbloom/grunt-debian-package
*
* Copyright (c) 2014 James Bloom
* Licensed under the MIT license.
*/
var fileSystem = require('./fileOrDirectory.js');
var replace = require('./replace.js');
module.exports = function (grunt) {
'use strict';
var _validateOptions = require('./options.js')._validate(grunt),
_copy = fileSystem._copy(grunt),
_cleanUp = fileSystem._cleanUp(grunt),
_findAndReplace = replace._findAndReplace(grunt),
_transformAndReplace = replace._transformAndReplace(grunt),
preparePackageContents = function (makefile, files, follow_soft_links, quiet) {
_transformAndReplace([makefile], '\\$\\{file_list\\}', files, function (file) {
return file.src.filter(function (filepath) {
if (!grunt.file.exists(filepath)) {
grunt.log.warn('File \'' + filepath + '\' not found');
return false;
} else {
return !grunt.file.isDir(filepath);
}
}).map(function (filepath) {
if (!quiet) {
grunt.log.writeln('Adding \'' + filepath + '\' to \'' + file.dest + '\'');
}
var soft_links_argument = "-P ";
// $$ = $ in JS
// next task `replace` is going to interpret $$ as $
// $$ = $ in make
// \$ = $ in bash
var make_filepath = filepath.replace(/\$/g, '\\$$$$$$$$');
var make_filedest = file.dest.replace(/\$/g, '\\$$$$$$$$');
return '\tmkdir -p "$(DESTDIR)' + file.dest.substr(0, file.dest.lastIndexOf('/')) + '" && cp -a ' + (follow_soft_links ? "" : "-P ") + '"' + process.cwd() + '/' + make_filepath + '" "$(DESTDIR)' + make_filedest + '"\n';
}).join('');
});
};
grunt.registerMultiTask('debian_package', 'Create debian package from grunt build', function () {
// tell Grunt this task is asynchronous.
var done = this.async();
// Merge task-specific and/or target-specific options with these defaults.
var pkg = grunt.file.readJSON('package.json'),
options = this.options({
maintainer: process.env.DEBFULLNAME && process.env.DEBEMAIL && {
name: process.env.DEBFULLNAME,
email: process.env.DEBEMAIL
} || pkg.author && pkg.author.name && pkg.author.email && pkg.author,
name: pkg.name,
prefix: "",
postfix: "",
short_description: (pkg.description && pkg.description.split(/\r\n|\r|\n/g)[0]) || '',
long_description: (pkg.description && pkg.description.split(/\r\n|\r|\n/g).splice(1).join(' ')) || '',
version: pkg.version,
build_number: process.env.BUILD_NUMBER || process.env.DRONE_BUILD_NUMBER || process.env.TRAVIS_BUILD_NUMBER || '1',
working_directory: 'tmp/',
packaging_directory_name: 'packaging',
target_architecture: "all",
category: "misc",
disable_debuild_deps_check: false
}),
spawn = require('child_process').spawn,
dateFormat = require('dateformat'),
now = dateFormat(new Date(), 'ddd, d mmm yyyy h:MM:ss +0000'),
temp_directory = options.working_directory + options.packaging_directory_name,
controlDirectory = temp_directory + '/debian',
changelog = controlDirectory + '/changelog',
control = controlDirectory + '/control',
links = controlDirectory + '/links',
dirs = controlDirectory + '/dirs',
makefile = temp_directory + '/Makefile',
dependencies = '';
if (!_validateOptions(options, options.quiet)) {
return done(false);
}
_cleanUp(options, true);
_copy(__dirname + '/../' + options.packaging_directory_name, temp_directory);
if (options.custom_template) {
_copy(options.custom_template, temp_directory);
}
// set environment variables if they are not already set
process.env.DEBFULLNAME = options.maintainer.name;
process.env.DEBEMAIL = options.maintainer.email;
if (options.dependencies) {
dependencies = ', ' + options.dependencies;
}
// generate packaging control files
_transformAndReplace([links], '\\$\\{softlinks\\}', options.links || [], function (softlink) {
return softlink.target + ' ' + softlink.source + '\n';
});
_transformAndReplace([dirs], '\\$\\{directories\\}', options.directories || [], function (directory) {
return directory + '\n';
});
_findAndReplace([changelog, control], '\\$\\{maintainer.name\\}', options.maintainer.name);
_findAndReplace([changelog, control], '\\$\\{maintainer.email\\}', options.maintainer.email);
_findAndReplace([changelog], '\\$\\{date\\}', now);
_findAndReplace([changelog, control, links, dirs], '\\$\\{name\\}', options.package_name);
_findAndReplace([control], '\\$\\{short_description\\}', options.short_description);
_findAndReplace([control], '\\$\\{long_description\\}', options.long_description);
_findAndReplace([changelog, control, links, dirs], '\\$\\{version\\}', options.version);
_findAndReplace([changelog, control, links, dirs], '\\$\\{build_number\\}', options.build_number);
_findAndReplace([control], '\\$\\{dependencies\\}', dependencies);
_findAndReplace([control], '\\$\\{target_architecture\\}', options.target_architecture);
_findAndReplace([control], '\\$\\{category\\}', options.category);
preparePackageContents(makefile, this.files, options.follow_soft_links, options.quiet);
// copy package lifecycle scripts
var scripts = ['preinst', 'postinst', 'prerm', 'postrm'];
for (var i = 0; i < scripts.length; i++) {
if (options[scripts[i]]) {
var destination = controlDirectory + '/' + scripts[i];
grunt.verbose.writeln(JSON.stringify(options[scripts[i]]));
if (options[scripts[i]].src) {
grunt.file.copy(options[scripts[i]].src, destination);
} else if (options[scripts[i]].contents) {
grunt.file.write(destination, options[scripts[i]].contents);
}
}
}
// run packaging binaries (i.e. build process)
grunt.verbose.writeln('Running \'debuild --no-tgz-check -sa -us -uc --lintian-opts --suppress-tags tar-errors-from-data,tar-errors-from-control,dir-or-file-in-var-www\'');
if (!options.simulate) {
if (grunt.file.exists('/usr/bin/debuild')) {
var checkDeps = options.disable_debuild_deps_check ? "-d" : "-D";
var debuild = spawn('debuild', ['--no-tgz-check', '-sa', checkDeps, '-us', '-uc', '--lintian-opts', '--suppress-tags', 'tar-errors-from-data,tar-errors-from-control,dir-or-file-in-var-www'], {
cwd: temp_directory,
stdio: [ 'ignore', (grunt.option('verbose') ? process.stdout : 'ignore'), process.stderr ]
});
debuild.on('exit', function (code) {
if (code !== 0) {
var logFile = grunt.file.read(grunt.file.expand(options.package_location + '*.build'));
grunt.log.subhead('\nerror running debuild!!');
if (logFile.search("Unmet\\sbuild\\sdependencies\\:\\sdebhelper") !== -1) {
grunt.log.warn('debhelper dependency not found try running \'sudo apt-get install debhelper\'');
}
done(false);
} else {
_cleanUp(options);
grunt.log.ok('Created package: ' + grunt.file.expand(options.package_location + '*.deb'));
if (options.repository) {
grunt.verbose.writeln('Running \'dput ' + options.repository + ' ' + grunt.file.expand(options.package_location + '*.changes') + '\'');
require('fs').chmodSync("" + grunt.file.expand(options.package_location + '*.changes'), "744");
var dputArguments = [options.repository, grunt.file.expand(options.package_location + '*.changes')];
if (grunt.option('verbose')) {
dputArguments.unshift('-d');
}
var dput = spawn('dput', dputArguments, {
stdio: [ 'ignore', (grunt.option('verbose') ? process.stdout : 'ignore'), process.stderr ]
});
dput.on('exit', function (code) {
if (code !== 0) {
grunt.log.subhead('\nerror uploading package using dput!!');
} else {
grunt.log.ok('Uploaded package: ' + grunt.file.expand(options.package_location + '*.deb'));
}
done(true);
});
} else {
done(true);
}
}
});
} else {
_cleanUp(options);
grunt.log.subhead('\n\'debuild\' executable not found!!');
grunt.log.warn('to install debuild try running \'sudo apt-get install devscripts\'');
return done(false);
}
} else {
return done(true);
}
}
);
};