denis-sokolov/remote-dotfiles

View on GitHub
src/util.js

Summary

Maintainability
A
0 mins
Test Coverage
'use strict';

var concat = require('gulp-concat');
var through2 = require('through2');
var Vinyl = require('vinyl');
var vinylFs = require('vinyl-fs');

var not = function(f){
    return function(){
        return !f.apply(this, arguments);
    };
};

var api = {};

api.append = function(txt){
    return through2.obj(function(chunk, enc, cb){
        chunk.contents = Buffer.concat([
            chunk.contents,
            new Buffer('\n' + txt.trim() + '\n')
        ]);
        this.push(chunk);
        cb();
    });
};

api.concat = concat;

api.comment = function(chr, txt){
    return (
        'This file is automatically generated and overwritten\n' +
        'It is handled by remote-dotfiles engine.\n' +
        (txt || '')
    )
        .split('\n')
        .map(function(l){ return chr + l + '\n'; })
        .join('');
};

api.comment.stream = function(chr, txt){
    return through2.obj(function(chunk, enc, cb){
        chunk.contents = Buffer.concat([
            new Buffer(api.comment(chr, txt)),
            chunk.contents
        ]);
        this.push(chunk);
        cb();
    });
};

/**
 * A function to rename files in a stream, only considering the relative path
 * @param {Function} f name -> new name
 * @return {Function}
 */
api.rename = function(f){
    return through2.obj(function(chunk, enc, cb){
        this.push(new Vinyl({
            contents: chunk.contents,
            path: '/' + f(chunk.relative),
            base: '/'
        }));
        cb();
    });
};

api.progress = function(count, cb){
    var done = 0;
    return function(){
        done += 1;
        cb(done / count);
    };
};

api.setting = function(app, name, type){
    var f = api.settings(app, name, type);
    return function(){
        return (f() || [])[0];
    };
};

api.settings = function(app, name, type){
    var args;
    var called = false;

    app[name] = function(){
        if (called) throw new Error('Can not change settings once set');
        called = true;
        args = Array.prototype.slice.call(arguments);
        if (type && args.filter(not(type)).length)
            throw new Error('Invalid argument type');
        return app;
    };

    return function(){
        return args;
    };
};

var getSingleSource = function(param, target){
    if (typeof param === 'function')
        param = param(target);
    if (param[0] === '/')
        return vinylFs.src(param);
    var stream = through2.obj();
    stream.push(new Vinyl({
        contents: new Buffer(param),
        path: '/tmp/pseudo'
    }));
    stream.end();
    return stream;
};

// Like vinyl-fs.src, but allows some of the globs to be raw file data,
// if does not begin with a slash, and dynamic data if a function.
// Can't simply filter and pipe to ensure the order.
api.src = function(params, target){
    params = [].concat.apply([], params);

    var stream = through2.obj();

    if (params.length === 0) {
        stream.end();
        return stream;
    }

    var first = params[0];
    var rest = params.slice(1);

    var source = getSingleSource(first, target);
    source.pipe(stream, {end: false});
    source.on('end', function(){
        api.src(rest, target).pipe(stream);
    });

    return stream;
};

module.exports = api;