mirror of
https://github.com/shelljs/shelljs.git
synced 2026-01-18 16:03:37 +00:00
Adds two new methods to src/common.js, common.statFollowLinks and common.statNoFollowLinks, which wrap fs.statSync and fs.lstatSync, respectively. This change is meant to improve readability and clarify intent. * Add common.statFollowLinks and common.statNoFollowLinks * Replace fs.statSync and fs.lstatSync in source files
176 lines
4.7 KiB
JavaScript
176 lines
4.7 KiB
JavaScript
import crypto from 'crypto';
|
|
import fs from 'fs';
|
|
|
|
import test from 'ava';
|
|
|
|
import shell from '..';
|
|
import common from '../src/common';
|
|
import utils from './utils/utils';
|
|
|
|
test.beforeEach(t => {
|
|
t.context.tmp = utils.getTempDir();
|
|
shell.config.resetForTesting();
|
|
shell.mkdir(t.context.tmp);
|
|
});
|
|
|
|
test.afterEach.always(t => {
|
|
shell.rm('-rf', t.context.tmp);
|
|
});
|
|
|
|
// Helper functions
|
|
function resetUtimes(f) {
|
|
const d = new Date();
|
|
d.setYear(2000);
|
|
fs.utimesSync(f, d, d);
|
|
return common.statFollowLinks(f);
|
|
}
|
|
|
|
function tmpFile(t, noCreate) {
|
|
const str = crypto.randomBytes(Math.ceil(10 / 2)).toString('hex');
|
|
const file = `${t.context.tmp}/${str}`;
|
|
if (!noCreate) {
|
|
fs.closeSync(fs.openSync(file, 'a'));
|
|
}
|
|
return file;
|
|
}
|
|
|
|
|
|
//
|
|
// Valids
|
|
//
|
|
|
|
test('should handle args', t => {
|
|
const result = shell.touch();
|
|
t.truthy(shell.error());
|
|
t.is(result.code, 1);
|
|
});
|
|
|
|
test('arguments must be strings', t => {
|
|
const result = shell.touch(1);
|
|
t.truthy(shell.error());
|
|
t.is(result.code, 1);
|
|
});
|
|
|
|
test('exits without error when trying to touch a directory', t => {
|
|
const result = shell.touch(t.context.tmp);
|
|
t.falsy(shell.error());
|
|
t.is(result.code, 0);
|
|
});
|
|
|
|
test('creates new files', t => {
|
|
const testFile = tmpFile(t);
|
|
const result = shell.touch(testFile);
|
|
t.truthy(fs.existsSync(testFile));
|
|
t.is(result.code, 0);
|
|
});
|
|
|
|
test('does not create a file if told not to', t => {
|
|
const testFile = tmpFile(t, true);
|
|
const result = shell.touch('-c', testFile);
|
|
t.is(result.code, 0);
|
|
t.falsy(fs.existsSync(testFile));
|
|
});
|
|
|
|
test('handles globs correctly', t => {
|
|
shell.touch(`${t.context.tmp}/file.txt`);
|
|
shell.touch(`${t.context.tmp}/file.js`);
|
|
const result = shell.touch(`${t.context.tmp}/file*`);
|
|
t.is(result.code, 0);
|
|
const files = shell.ls(`${t.context.tmp}/file*`);
|
|
t.truthy(files.indexOf(`${t.context.tmp}/file.txt`) > -1);
|
|
t.truthy(files.indexOf(`${t.context.tmp}/file.js`) > -1);
|
|
t.is(files.length, 2);
|
|
});
|
|
|
|
test('errors if reference file is not found', t => {
|
|
const testFile = tmpFile(t);
|
|
const refFile = tmpFile(t, true);
|
|
const result = shell.touch({ '-r': refFile }, testFile);
|
|
t.is(result.code, 1);
|
|
t.truthy(shell.error());
|
|
});
|
|
|
|
test('uses a reference file for mtime', t => {
|
|
const testFile = tmpFile(t);
|
|
const testFile2 = tmpFile(t);
|
|
shell.touch(testFile2);
|
|
utils.sleep(1000);
|
|
let result = shell.touch(testFile);
|
|
t.falsy(shell.error());
|
|
t.is(result.code, 0);
|
|
t.not(
|
|
common.statFollowLinks(testFile).mtime.getTime(),
|
|
common.statFollowLinks(testFile2).mtime.getTime()
|
|
);
|
|
t.not(
|
|
common.statFollowLinks(testFile).atime.getTime(),
|
|
common.statFollowLinks(testFile2).atime.getTime()
|
|
);
|
|
result = shell.touch({ '-r': testFile2 }, testFile);
|
|
t.falsy(shell.error());
|
|
t.is(result.code, 0);
|
|
t.is(
|
|
common.statFollowLinks(testFile).mtime.getTime(),
|
|
common.statFollowLinks(testFile2).mtime.getTime()
|
|
);
|
|
t.is(
|
|
common.statFollowLinks(testFile).atime.getTime(),
|
|
common.statFollowLinks(testFile2).atime.getTime()
|
|
);
|
|
});
|
|
|
|
test('sets mtime and atime by default', t => {
|
|
const testFile = tmpFile(t);
|
|
const oldStat = resetUtimes(testFile);
|
|
const result = shell.touch(testFile);
|
|
t.is(result.code, 0);
|
|
t.truthy(oldStat.mtime < common.statFollowLinks(testFile).mtime);
|
|
t.truthy(oldStat.atime < common.statFollowLinks(testFile).atime);
|
|
});
|
|
|
|
test('does not set mtime if told not to', t => {
|
|
const testFile = tmpFile(t);
|
|
const oldStat = resetUtimes(testFile);
|
|
const result = shell.touch('-a', testFile);
|
|
t.is(result.code, 0);
|
|
t.is(oldStat.mtime.getTime(), common.statFollowLinks(testFile).mtime.getTime());
|
|
});
|
|
|
|
test('does not set atime if told not to', t => {
|
|
const testFile = tmpFile(t);
|
|
const oldStat = resetUtimes(testFile);
|
|
const result = shell.touch('-m', testFile);
|
|
t.is(result.code, 0);
|
|
t.is(oldStat.atime.getTime(), common.statFollowLinks(testFile).atime.getTime());
|
|
});
|
|
|
|
test('multiple files', t => {
|
|
const testFile = tmpFile(t, true);
|
|
const testFile2 = tmpFile(t, true);
|
|
shell.rm('-f', testFile, testFile2);
|
|
const result = shell.touch(testFile, testFile2);
|
|
t.is(result.code, 0);
|
|
t.truthy(fs.existsSync(testFile));
|
|
t.truthy(fs.existsSync(testFile2));
|
|
});
|
|
|
|
test('file array', t => {
|
|
const testFile = tmpFile(t, true);
|
|
const testFile2 = tmpFile(t, true);
|
|
shell.rm('-f', testFile, testFile2);
|
|
const result = shell.touch([testFile, testFile2]);
|
|
t.is(result.code, 0);
|
|
t.truthy(fs.existsSync(testFile));
|
|
t.truthy(fs.existsSync(testFile2));
|
|
});
|
|
|
|
test('touching broken link creates a new file', t => {
|
|
utils.skipOnWin(t, () => {
|
|
const result = shell.touch('test/resources/badlink');
|
|
t.is(result.code, 0);
|
|
t.falsy(shell.error());
|
|
t.truthy(fs.existsSync('test/resources/not_existed_file'));
|
|
shell.rm('test/resources/not_existed_file');
|
|
});
|
|
});
|