Search code examples
gulp

gulp-rsync ignores symbolic links


I want to synchronize a directory, which contains a symbolic link. This link should be transferred as symbolic link.

The documentation of gulp-rsync explains the option links which seems to cover this.

First problem with gulp.src (which does not support symbolic links) can be solved by using vinyl-fs. Works fine except the symbolic link, which is ignored, although listed by gulpDebug().

The used gulpfile.js task looks like:

const gulp = require('gulp'),
      gulpDebug = require('gulp-debug'),
      merge = require('merge-stream'),
      rsync = require('gulp-rsync'),
      vfs = require('vinyl-fs');

gulp.task('rsyncFiles', function (done) {
    const rsyncSrcClient =
        vfs.src('src/**')
            .pipe(gulpDebug())
            .pipe(rsync({
                root: 'src/',
                hostname: remoteHostname,
                destination: remoteTargetDir + '/src/',
                links: true
            }));

    return merge(rsyncSrcClient);
});

Using rsync --link ... manually from shell works as desired, the symbolic link is transferred as symbolic link.


Solution

  • Adding the option emptyDirectories: true solves the problem.

    The gulpfile.js is now:

    gulp.task('rsyncFiles', function (done) {
        const rsyncSrcClient =
            vfs.src('src/**')
                .pipe(gulpDebug())
                .pipe(rsync({
                    root: 'src/',
                    hostname: remoteHostname,
                    destination: remoteTargetDir + '/src/',
                    links: true,
                    emptyDirectories: true
                }));
    
        return merge(rsyncSrcClient);
    });
    

    Reason is the filtering mechanism inside the file node_modules/gulp-rsync/index.js.

    On index.js#L49 there is the following source-snippet which is always false for symbolic links:

    sources = sources.filter(function(source) {
        return !source.isNull() ||
               options.emptyDirectories ||
               (source.path === cwd && options.recursive);
    });
    

    Adding the option emptyDirectories: true changes this behavior to result true for symbolic links. Symbolic links are not longer filtered out and rsync is transferring the link as desired.