Skip to content

Commit

Permalink
Added multiple debug messages and fixed move tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
alinex committed May 11, 2014
1 parent ccb7442 commit 45e4ac4
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 32 deletions.
5 changes: 4 additions & 1 deletion src/copy.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ copy = module.exports.async = (source, target, options, cb, depth = 0) ->
mkdirs.async path.dirname(target), (err) ->
return cb err if err
# copy the file
debug "copying file #{source} to #{target}"
fs.exists target, (exists) ->
if exists and not (options.overwrite or options.ignore)
return cb new Error "Target file already exists."
if not exists or options.overwrite
debug "copying file #{source} to #{target}"
return copyFile source, stats, target, cb
cb()
else if stats.isSymbolicLink()
Expand Down Expand Up @@ -131,20 +131,23 @@ copySync = module.exports.sync = (source, target, options = {}, depth = 0) ->
if exists and not (options.overwrite or options.ignore)
throw new Error "Target file already exists."
if not exists or options.overwrite
debug "copying file #{source} to #{target}"
return copyFileSync source, stats, target
else if stats.isSymbolicLink()
return unless ok
# create directory if neccessary
mkdirs.sync path.dirname(target)
resolvedPath = fs.readlinkSync source
# make the symlink
debug "copying link #{source} to #{target}"
fs.symlinkSync resolvedPath, target
else
# source is directory
depth++
# copy directory
mkdirs.sync target, stats.mode if ok
# copy all files in directory
debug "copying directory #{source} to #{target}"
for file in fs.readdirSync source
copySync path.join(source, file), path.join(target, file), options, depth

Expand Down
90 changes: 65 additions & 25 deletions src/filter.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ path = require 'path'
async = require 'async'
{execFile} = require 'child_process'
chrono = require 'chrono-node'
debug = require('debug')('fs:filter')
util = require 'util'

# Find files
# -------------------------------------------------
Expand All @@ -26,8 +28,10 @@ chrono = require 'chrono-node'
# * `callback(success)`
# The callback will be called with a boolean value showing if file is accepted.
module.exports.async = (file, depth, options = {}, cb = -> ) ->
return unless options
debug "check #{file} for " + util.inspect options
async.parallel [
(cb) -> skipDepth depth, options, cb
(cb) -> skipDepth file, depth, options, cb
(cb) -> skipPath file, options, cb
(cb) -> skipType file, options, cb
(cb) -> skipSize file, options, cb
Expand Down Expand Up @@ -57,8 +61,10 @@ module.exports.async = (file, depth, options = {}, cb = -> ) ->
#
# The options are the same as in the asynchronous method.
module.exports.sync = (file, depth, options = {}) ->
return unless options
debug "check #{file} for " + util.inspect options
return false if skipTypeSync file, options
return false if skipDepthSync depth, options
return false if skipDepthSync file, depth, options
return false if skipPathSync file, options
return false if skipSizeSync file, options
return false if skipTimeSync file, options
Expand All @@ -82,27 +88,38 @@ skipPathSync = (file, options) ->
return false unless options.include or options.exclude
if options.include
if options.include instanceof RegExp
return true unless file.match options.include
unless file.match options.include
debug "skip #{file} because path not included"
return true
else
minimatch = require 'minimatch'
return true unless minimatch file, options.include, { matchBase: true }
unless minimatch file, options.include, { matchBase: true }
debug "skip #{file} because path not included"
return true
if options.exclude
if options.exclude instanceof RegExp
return true if file.match options.exclude
if file.match options.exclude
debug "skip #{file} because path excluded"
return true
else
minimatch = require 'minimatch'
return true if minimatch file, options.exclude, { matchBase: true }
if minimatch file, options.exclude, { matchBase: true }
debug "skip #{file} because path excluded"
return true
return false

# ### Test the file depth
# The depth calculation has to be done in the traversing method this will only
# check the value against the options.
skipDepth = (depth, options, cb) ->
cb skipDepthSync depth, options
skipDepth = (file, depth, options, cb) ->
cb skipDepthSync file, depth, options

skipDepthSync = (depth, options) ->
return (options.mindepth? and options.mindepth > depth) or
skipDepthSync = (file, depth, options) ->
skip = (options.mindepth? and options.mindepth > depth) or
(options.maxdepth? and options.maxdepth < depth)
debug "skip #{file} because not in specified depth" if skip
return skip


# ### Test the file type
skipType = (file, options, cb) ->
Expand All @@ -112,15 +129,20 @@ skipType = (file, options, cb) ->
return cb err if err
switch options.type
when 'file', 'f'
return cb not stats.isFile()
return cb() if stats.isFile()
debug "skip #{file} because not a file entry"
when 'directory', 'dir', 'd'
return cb not stats.isDirectory()
return cb() if stats.isDirectory()
debug "skip #{file} because not a directory entry"
when 'link', 'l'
return cb not stats.isSymbolicLink()
return cb() if stats.isSymbolicLink()
debug "skip #{file} because not a link entry"
when 'fifo', 'pipe', 'p'
return cb not stats.isFIFO()
return cb() if stats.isFIFO()
debug "skip #{file} because not a FIFO entry"
when 'socket', 's'
return cb not stats.isSocket()
return cb() if stats.isSocket()
debug "skip #{file} because not a socket entry"
return cb true

skipTypeSync = (file, options) ->
Expand All @@ -129,15 +151,20 @@ skipTypeSync = (file, options) ->
stats = stat file
switch options.type
when 'file', 'f'
return not stats.isFile()
return if stats.isFile()
debug "skip #{file} because not a file entry"
when 'directory', 'dir', 'd'
return not stats.isDirectory()
return if stats.isDirectory()
debug "skip #{file} because not a directory entry"
when 'link', 'l'
return not stats.isSymbolicLink()
return if stats.isSymbolicLink()
debug "skip #{file} because not a link entry"
when 'fifo', 'pipe', 'p'
return not stats.isFIFO()
return if stats.isFIFO()
debug "skip #{file} because not a FIFO entry"
when 'socket', 's'
return not stats.isSocket()
return if stats.isSocket()
debug "skip #{file} because not a socket entry"
return true

# ### Test for filesize
Expand All @@ -160,6 +187,7 @@ skipSize = (file, options, cb) ->
return cb err if err
skip = (options.minsize? and options.minsize > stats.size) or
(options.maxsize? and options.maxsize < stats.size)
debug "skip #{file} because size mismatch" if skip
cb skip

skipSizeSync = (file, options) ->
Expand All @@ -168,8 +196,10 @@ skipSizeSync = (file, options) ->
options.maxsize = sizeHumanToInt options.maxsize if options.maxsize
stat = if options.dereference? then fs.statSync else fs.lstatSync
stats = stat file
return (options.minsize? and options.minsize > stats.size) or
skip = (options.minsize? and options.minsize > stats.size) or
(options.maxsize? and options.maxsize < stats.size)
debug "skip #{file} because size mismatch" if skip
return skip

# ### Check the owwner and group
userToUid = (user, cb) ->
Expand Down Expand Up @@ -220,7 +250,9 @@ skipOwner = (file, options, cb) ->
stat file, (err, stats) ->
return cb err if err
# console.log file, uid, gid, stats.uid, stats.gid
cb (uid and uid is not stats.uid) or (gid and gid is not stats.gid)
skip = (uid and uid is not stats.uid) or (gid and gid is not stats.gid)
debug "skip #{file} because owner mismatch" if skip
cb skip

skipOwnerSync = (file, options) ->
return false unless options.user or options.group
Expand All @@ -229,7 +261,9 @@ skipOwnerSync = (file, options) ->
stat = if options.dereference? then fs.statSync else fs.lstatSync
stats = stat file
# console.log file, uid, gid, stats.uid, stats.gid
return (uid and uid is not stats.uid) or (gid and gid is not stats.gid)
skip = (uid and uid is not stats.uid) or (gid and gid is not stats.gid)
debug "skip #{file} because owner mismatch" if skip
return skip


# ### User provided test
Expand All @@ -238,11 +272,14 @@ skipOwnerSync = (file, options) ->
skipFunction = (file, options, cb) ->
return cb() unless options.test or typeof options.test is not 'function'
options.test file, options, (ok) ->
debug "skip #{file} by user function" unless ok
cb not ok

skipFunctionSync = (file, options) ->
return false unless options.test or typeof options.test is not 'function'
return not options.test file, options
ok = options.test file, options
debug "skip #{file} by user function" unless ok
return not ok

# ### Check file times
# All timestamps maybe checked with before and after to select the files.
Expand Down Expand Up @@ -275,6 +312,7 @@ skipTime = (file, options, cb) ->
# console.log file, stats
skip = not timeCheck stats, options
# console.log file, skip
debug "skip #{file} because out of time range" if skip
cb skip

skipTimeSync = (file, options) ->
Expand All @@ -285,4 +323,6 @@ skipTimeSync = (file, options) ->
return false unless used
stat = if options.dereference? then fs.statSync else fs.lstatSync
stats = stat file
return not timeCheck stats, options
skip = not timeCheck stats, options
debug "skip #{file} because out of time range" if skip
return skip
4 changes: 2 additions & 2 deletions src/move.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module.exports.async = (source, target, options = {}, cb = ->) ->
if typeof options is 'function' or not options
cb = options ? ->
options = {}
debug "Move filepath #{source} to #{target}."
debug "move filepath #{source} to #{target}."
# collect methods to run
async.series [
# remove old target first
Expand Down Expand Up @@ -98,7 +98,7 @@ copyRemove = (source, target, options, cb) ->
# * `Error`
# If anything out of order happened.
module.exports.sync = (source, target, options = {}) ->
debug "Move filepath #{source} to #{target}."
debug "move filepath #{source} to #{target}."
# remove old target first
if options.clean
remove.sync target
Expand Down
3 changes: 3 additions & 0 deletions src/remove.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,21 @@ removeSync = module.exports.sync = (file, options = {}, depth = 0) ->
if stats.isFile()
return unless ok
# remove file
debug "removing file #{file}"
fs.unlinkSync file
return file
else if stats.isSymbolicLink()
return unless ok
# remove symbolic link
debug "removing link #{file}"
fs.unlinkSync file
return file
else if stats.isDirectory()
# file is directory
dir = file
depth++
# if this dir should be removed, use no filtering for the containing parts
debug "removing directory #{file}"
options = {} if ok
files = fs.readdirSync file
# copy all files in directory
Expand Down
6 changes: 3 additions & 3 deletions test/mocha/move.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ describe "Move", ->
expect(err, 'error').to.exist
cb()

it.only "should move dir with filter", (cb) ->
it "should move dir with filter", (cb) ->
fs.move 'test/temp/dir1', 'test/temp/dir4',
include: '*1'
include: '*le11'
, (err) ->
expect(err, 'error').to.not.exist
expect(fs.existsSync('test/temp/dir4'), 'new dir').to.be.true
Expand Down Expand Up @@ -151,7 +151,7 @@ describe "Move", ->

it "should move dir with filter", ->
fs.moveSync 'test/temp/dir1', 'test/temp/dir4',
include: '*le1'
include: '*le11'
expect(fs.existsSync('test/temp/dir4'), 'new dir').to.be.true
expect(fs.existsSync('test/temp/dir1'), 'old dir').to.be.true
expect(fs.readdirSync('test/temp/dir4'), 'new dir').to.deep.equal ['file11']
Expand Down
2 changes: 1 addition & 1 deletion test/mocha/remove.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ expect = chai.expect

describe "Remove", ->

fs = require '../../lib/index'
fs = require '../../src/index'

beforeEach (cb) ->
exec 'mkdir -p test/temp/dir1', ->
Expand Down

0 comments on commit 45e4ac4

Please sign in to comment.