wr
Version:
watch files and run a command when they change
154 lines (116 loc) • 4.9 kB
text/coffeescript
#-------------------------------------------------------------------------------
# Copyright (c) 2012 Patrick Mueller
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
fs = require 'fs'
path = require 'path'
Executor = require './Executor'
FileWatcher = require './FileWatcher'
existsSync = fs.existsSync || path.existsSync
#-------------------------------------------------------------------------------
module.exports = class FileSet
#---------------------------------------------------------------------------
constructor: (@files, @opts) ->
@allFiles = []
@allMtimes = {}
@chimeTimeout = null
@opts.logError = (->) if !@opts.logError
@opts.logSuccess = (->) if !@opts.logSuccess
@opts.logInfo = (->) if !@opts.logInfo
@executor = Executor.getExecutor(@, @opts)
@childProcess = null
@childStartTime = 0
#---------------------------------------------------------------------------
getMtime: (fileName) ->
@allMtimes[fileName] || 0
#---------------------------------------------------------------------------
whenChangedRun: (@cmd) ->
@expandFiles()
if @allFiles.length == 0
@logError "no files found to watch"
return
@chime()
@watchFiles()
#---------------------------------------------------------------------------
fileChanged: () ->
@fileWatcher = null
@runCommand()
#---------------------------------------------------------------------------
chime: ->
@logInfo "watching #{@allFiles.length} files, running '#{@cmd}'"
@resetChime()
#---------------------------------------------------------------------------
resetChime: ->
return if !@opts.chime
clearTimeout(@chimeTimeout) if @chimeTimeout
@chimeTimeout = setTimeout(
=> @chime(),
1000 * 60 * @opts.chime
)
#---------------------------------------------------------------------------
resetAfterCommand: ->
@expandFiles()
if @allFiles.length == 0
@logError("no files found to watch")
return
@watchFiles()
@resetChime()
#---------------------------------------------------------------------------
runCommand: ->
@opts.logInfo "running '#{@cmd}'"
if @childProcess
if Date.now() - @childStartTime > 5000
@childProcess.kill()
@childStartTime = Date.now()
@childProcess = @executor.run(@cmd)
@childProcess.on "exit", =>
@childProcess = null
#---------------------------------------------------------------------------
expandFiles: ->
@allFiles = []
@allMtimes = {}
for file in @files
@expandFile(file)
#---------------------------------------------------------------------------
expandFile: (fileName) ->
if !existsSync(fileName)
@logError("File not found '#{fileName}'")
return
stats = fs.statSync(fileName)
if stats.isFile()
@allFiles.push(fileName)
@allMtimes[fileName] = stats.mtime.getTime()
else if stats.isDirectory()
@allFiles.push(fileName)
@allMtimes[fileName] = stats.mtime.getTime()
entries = fs.readdirSync(fileName)
for entry in entries
@expandFile path.join(fileName, entry)
#---------------------------------------------------------------------------
watchFiles: ->
@fileWatcher = FileWatcher.get(@, @opts)
@fileWatcher.watch(@allFiles)
#---------------------------------------------------------------------------
logSuccess: (message) ->
@opts.logSuccess message
#---------------------------------------------------------------------------
logError: (message) ->
@opts.logError message
#---------------------------------------------------------------------------
logInfo: (message) ->
@opts.logInfo message
#---------------------------------------------------------------------------
logVerbose: (message) ->
return if not @opts.verbose
@opts.logInfo message