text: // Generated by CoffeeScript 1.6.3
  (function() {
    var Backbone, FileModel, Model, TaskGroup, docpadUtil, encodingUtil, extendr, extractOptsAndCallback, isTextOrBinary, jschardet, mime, pathUtil, safefs, typeChecker, _ref, _ref1,
      __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
      __hasProp = {}.hasOwnProperty,
      __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
      __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
      __slice = [].slice;
  
    pathUtil = require('path');
  
    isTextOrBinary = require('istextorbinary');
  
    typeChecker = require('typechecker');
  
    TaskGroup = require('taskgroup').TaskGroup;
  
    safefs = require('safefs');
  
    mime = require('mime');
  
    extendr = require('extendr');
  
    extractOptsAndCallback = require('extract-opts').extractOptsAndCallback;
  
    jschardet = null;
  
    encodingUtil = null;
  
    _ref = require('../base'), Backbone = _ref.Backbone, Model = _ref.Model;
  
    docpadUtil = require('../util');
  
    FileModel = (function(_super) {
      __extends(FileModel, _super);
  
      function FileModel() {
        this.action = __bind(this.action, this);
        _ref1 = FileModel.__super__.constructor.apply(this, arguments);
        return _ref1;
      }
  
      FileModel.prototype.klass = FileModel;
  
      FileModel.prototype.type = 'file';
  
      FileModel.prototype.rootOutDirPath = null;
  
      FileModel.prototype.detectEncoding = false;
  
      FileModel.prototype.stat = null;
  
      FileModel.prototype.buffer = null;
  
      FileModel.prototype.bufferTime = null;
  
      FileModel.prototype.meta = null;
  
      FileModel.prototype.getOptions = function() {
        return {
          detectEncoding: this.detectEncoding,
          rootOutDirPath: this.rootOutDirPath,
          stat: this.stat,
          buffer: this.buffer,
          meta: this.meta
        };
      };
  
      FileModel.prototype.isOption = function(key) {
        var names, result;
        names = ['detectEncoding', 'rootOutDirPath', 'stat', 'data', 'buffer', 'meta'];
        result = __indexOf.call(names, key) >= 0;
        return result;
      };
  
      FileModel.prototype.extractOptions = function(attrs) {
        var key, result, value;
        result = {};
        for (key in attrs) {
          if (!__hasProp.call(attrs, key)) continue;
          value = attrs[key];
          if (this.isOption(key)) {
            result[key] = value;
            delete attrs[key];
          }
        }
        return result;
      };
  
      FileModel.prototype.setOptions = function(attrs) {
        if (attrs == null) {
          attrs = {};
        }
        if (attrs.detectEncoding != null) {
          this.rootOutDirPath = attrs.detectEncoding;
          delete this.attributes.detectEncoding;
        }
        if (attrs.rootOutDirPath != null) {
          this.rootOutDirPath = attrs.rootOutDirPath;
          delete this.attributes.rootOutDirPath;
        }
        if (attrs.stat != null) {
          this.setStat(attrs.stat);
          delete this.attributes.stat;
        }
        if (attrs.data != null) {
          this.setBuffer(attrs.data);
          delete this.attributes.data;
        }
        if (attrs.buffer != null) {
          this.setBuffer(attrs.buffer);
          delete this.attributes.buffer;
        }
        if (attrs.meta != null) {
          this.setMeta(attrs.meta);
          delete this.attributes.meta;
        }
        return this;
      };
  
      FileModel.prototype.clone = function() {
        var attrs, instance, opts;
        attrs = this.getAttributes();
        opts = this.getOptions();
        delete attrs.id;
        instance = new this.klass(attrs, opts);
        return instance;
      };
  
      FileModel.prototype.defaults = {
        id: null,
        basename: null,
        outBasename: null,
        extension: null,
        outExtension: null,
        extensions: null,
        filename: null,
        fullPath: null,
        fullDirPath: null,
        outPath: null,
        outDirPath: null,
        outFilename: null,
        relativePath: null,
        relativeOutPath: null,
        relativeDirPath: null,
        relativeOutDirPath: null,
        relativeBase: null,
        relativeOutBase: null,
        contentType: null,
        outContentType: null,
        ctime: null,
        mtime: null,
        rtime: null,
        wtime: null,
        exists: null,
        encoding: null,
        source: null,
        content: null,
        tags: null,
        render: false,
        write: true,
        writeSource: false,
        dynamic: false,
        title: null,
        name: null,
        date: null,
        slug: null,
        url: null,
        urls: null,
        ignored: false,
        standalone: false
      };
  
      FileModel.prototype.setBuffer = function(buffer) {
        if (!Buffer.isBuffer(buffer)) {
          buffer = new Buffer(buffer);
        }
        this.bufferTime = this.get('mtime') || new Date();
        this.buffer = buffer;
        return this;
      };
  
      FileModel.prototype.getBuffer = function() {
        return this.buffer;
      };
  
      FileModel.prototype.isBufferOutdated = function() {
        return (this.buffer != null) === false || this.bufferTime < (this.get('mtime') || new Date());
      };
  
      FileModel.prototype.setStat = function(stat) {
        this.stat = stat;
        this.set({
          ctime: new Date(stat.ctime),
          mtime: new Date(stat.mtime)
        });
        return this;
      };
  
      FileModel.prototype.getStat = function() {
        return this.stat;
      };
  
      FileModel.prototype.getAttributes = function(dereference) {
        var attrs;
        if (dereference == null) {
          dereference = true;
        }
        attrs = this.toJSON(dereference);
        delete attrs.id;
        return attrs;
      };
  
      FileModel.prototype.toJSON = function(dereference) {
        var data;
        if (dereference == null) {
          dereference = false;
        }
        data = FileModel.__super__.toJSON.apply(this, arguments);
        data.meta = this.getMeta().toJSON();
        if (dereference === true) {
          data = extendr.dereference(data);
        }
        return data;
      };
  
      FileModel.prototype.getMeta = function() {
        var args, _ref2;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        if (this.meta === null) {
          this.meta = new Model();
        }
        if (args.length) {
          return (_ref2 = this.meta).get.apply(_ref2, args);
        } else {
          return this.meta;
        }
      };
  
      FileModel.prototype.set = function(attrs, opts) {
        var newAttrs, options, _ref2;
        if (typeChecker.isString(attrs)) {
          newAttrs = {};
          newAttrs[attrs] = opts;
          return this.set(newAttrs, opts);
        }
        attrs = (_ref2 = typeof attrs.toJSON === "function" ? attrs.toJSON() : void 0) != null ? _ref2 : attrs;
        options = this.extractOptions(attrs);
        FileModel.__super__.set.call(this, attrs, opts);
        this.setOptions(options, opts);
        return this;
      };
  
      FileModel.prototype.setDefaults = function(attrs, opts) {
        var options, _ref2;
        attrs = (_ref2 = typeof attrs.toJSON === "function" ? attrs.toJSON() : void 0) != null ? _ref2 : attrs;
        options = this.extractOptions(attrs);
        FileModel.__super__.setDefaults.call(this, attrs, opts);
        this.setOptions(options, opts);
        return this;
      };
  
      FileModel.prototype.setMeta = function(attrs, opts) {
        var options, _ref2;
        attrs = (_ref2 = typeof attrs.toJSON === "function" ? attrs.toJSON() : void 0) != null ? _ref2 : attrs;
        options = this.extractOptions(attrs);
        this.getMeta().set(attrs, opts);
        this.set(attrs, opts);
        this.setOptions(options, opts);
        return this;
      };
  
      FileModel.prototype.setMetaDefaults = function(attrs, opts) {
        var options, _ref2;
        attrs = (_ref2 = typeof attrs.toJSON === "function" ? attrs.toJSON() : void 0) != null ? _ref2 : attrs;
        options = this.extractOptions(attrs);
        this.getMeta().setDefaults(attrs, opts);
        this.setDefaults(attrs, opts);
        this.setOptions(options, opts);
        return this;
      };
  
      FileModel.prototype.getFilename = function(opts) {
        var filename, fullPath, relativePath, result;
        if (opts == null) {
          opts = {};
        }
        fullPath = opts.fullPath, relativePath = opts.relativePath, filename = opts.filename;
        result = filename != null ? filename : this.get('filename');
        if (!result) {
          result = (fullPath != null ? fullPath : this.get('fullPath')) || (relativePath != null ? relativePath : this.get('relativePath'));
          if (result) {
            result = pathUtil.basename(result);
          }
        }
        result || (result = null);
        return result;
      };
  
      FileModel.prototype.getFilePath = function(opts) {
        var filename, fullPath, relativePath, result;
        if (opts == null) {
          opts = {};
        }
        fullPath = opts.fullPath, relativePath = opts.relativePath, filename = opts.filename;
        result = (fullPath != null ? fullPath : this.get('fullPath')) || (relativePath != null ? relativePath : this.get('relativePath')) || (filename != null ? filename : this.get('filename')) || null;
        return result;
      };
  
      FileModel.prototype.getExtensions = function(_arg) {
        var extensions, filename;
        extensions = _arg.extensions, filename = _arg.filename;
        extensions || (extensions = this.get('extensions') || null);
        if ((extensions || []).length === 0) {
          filename = this.getFilename({
            filename: filename
          });
          if (filename) {
            extensions = docpadUtil.getExtensions(filename);
          }
        }
        return extensions || null;
      };
  
      FileModel.prototype.getContent = function() {
        return this.get('content') || this.getBuffer();
      };
  
      FileModel.prototype.getOutContent = function() {
        return this.getContent();
      };
  
      FileModel.prototype.isText = function() {
        return this.get('encoding') !== 'binary';
      };
  
      FileModel.prototype.isBinary = function() {
        return this.get('encoding') === 'binary';
      };
  
      FileModel.prototype.setUrl = function(url) {
        this.addUrl(url);
        this.set({
          url: url
        });
        return this;
      };
  
      FileModel.prototype.addUrl = function(url) {
        var existingUrl, found, newUrl, urls, _i, _j, _len, _len1;
        if (url instanceof Array) {
          for (_i = 0, _len = url.length; _i < _len; _i++) {
            newUrl = url[_i];
            this.addUrl(newUrl);
          }
        } else if (url) {
          found = false;
          urls = this.get('urls');
          for (_j = 0, _len1 = urls.length; _j < _len1; _j++) {
            existingUrl = urls[_j];
            if (existingUrl === url) {
              found = true;
              break;
            }
          }
          if (!found) {
            urls.push(url);
          }
          this.trigger('change:urls', this, urls, {});
          this.trigger('change', this, {});
        }
        return this;
      };
  
      FileModel.prototype.removeUrl = function(userUrl) {
        var index, url, urls, _i, _len;
        urls = this.get('urls');
        for (index = _i = 0, _len = urls.length; _i < _len; index = ++_i) {
          url = urls[index];
          if (url === userUrl) {
            urls.splice(index, 1);
            break;
          }
        }
        return this;
      };
  
      FileModel.prototype.getPath = function(relativePath, parentPath) {
        var path, relativeDirPath;
        if (/^\./.test(relativePath)) {
          relativeDirPath = this.get('relativeDirPath');
          path = pathUtil.join(relativeDirPath, relativePath);
        } else {
          if (parentPath) {
            path = pathUtil.join(parentPath, relativePath);
          } else {
            path = relativePath;
          }
        }
        return path;
      };
  
      FileModel.prototype.actionRunnerInstance = null;
  
      FileModel.prototype.getActionRunner = function() {
        return this.actionRunnerInstance;
      };
  
      FileModel.prototype.action = function() {
        var args;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        return docpadUtil.action.apply(this, args);
      };
  
      FileModel.prototype.initialize = function(attrs, opts) {
        var file, now, _base, _base1, _base2, _base3, _base4;
        if (opts == null) {
          opts = {};
        }
        file = this;
        if (this.attributes == null) {
          this.attributes = {};
        }
        if ((_base = this.attributes).extensions == null) {
          _base.extensions = [];
        }
        if ((_base1 = this.attributes).urls == null) {
          _base1.urls = [];
        }
        now = new Date();
        if ((_base2 = this.attributes).ctime == null) {
          _base2.ctime = now;
        }
        if ((_base3 = this.attributes).mtime == null) {
          _base3.mtime = now;
        }
        if (this.id == null) {
          this.id = (_base4 = this.attributes).id != null ? (_base4 = this.attributes).id : _base4.id = this.cid;
        }
        this.setOptions(opts);
        this.actionRunnerInstance = new TaskGroup("file action runner").run().on('complete', function(err) {
          if (err) {
            return file.emit('error', err);
          }
        });
        FileModel.__super__.initialize.apply(this, arguments);
        return this;
      };
  
      FileModel.prototype.load = function(opts, next) {
        var file, filePath, fullPath, tasks, _ref2;
        if (opts == null) {
          opts = {};
        }
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        if (opts.exists == null) {
          opts.exists = null;
        }
        fullPath = this.get('fullPath');
        filePath = this.getFilePath({
          fullPath: fullPath
        });
        if (opts.exists != null) {
          file.set({
            exists: opts.exists
          });
        }
        if (opts.stat != null) {
          file.setStat(opts.stat);
        }
        if (opts.buffer != null) {
          file.setBuffer(opts.buffer);
        }
        tasks = new TaskGroup("load tasks for file: " + filePath, {
          next: next
        }).on('item.run', function(item) {
          return file.log("debug", "" + (item.getConfig().name) + ": " + file.type + ": " + filePath);
        });
        tasks.addTask("Detect the file", function(complete) {
          if (fullPath && opts.exists === null) {
            return safefs.exists(fullPath, function(exists) {
              opts.exists = exists;
              file.set({
                exists: opts.exists
              });
              return complete();
            });
          } else {
            return complete();
          }
        });
        tasks.addTask("Stat the file and cache the result", function(complete) {
          if (fullPath && opts.exists && (opts.stat != null) === false) {
            return safefs.stat(fullPath, function(err, fileStat) {
              if (err) {
                return complete(err);
              }
              file.setStat(fileStat);
              return complete();
            });
          } else {
            return complete();
          }
        });
        tasks.addTask("Read the file and cache the result", function(complete) {
          if (fullPath && opts.exists && (opts.buffer != null) === false && file.isBufferOutdated()) {
            return safefs.readFile(fullPath, function(err, buffer) {
              if (err) {
                return complete(err);
              }
              file.setBuffer(buffer);
              return complete();
            });
          } else {
            return complete();
          }
        });
        tasks.addTask("Load -> Parse", function(complete) {
          return file.parse(complete);
        });
        tasks.addTask("Parse -> Normalize", function(complete) {
          return file.normalize(complete);
        });
        tasks.addTask("Normalize -> Contextualize", function(complete) {
          return file.contextualize(complete);
        });
        tasks.run();
        return this;
      };
  
      FileModel.prototype.parse = function(opts, next) {
        var buffer, changes, content, d, encoding, err, isText, relativePath, source, _ref2, _ref3,
          _this = this;
        if (opts == null) {
          opts = {};
        }
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        buffer = this.getBuffer();
        relativePath = this.get('relativePath');
        encoding = opts.encoding || this.get('encoding') || null;
        changes = {};
        if (buffer && (encoding != null) === false || opts.reencode === true) {
          isText = isTextOrBinary.isTextSync(relativePath, buffer);
          if (isText === true) {
            if (this.detectEncoding) {
              if (jschardet == null) {
                jschardet = require('jschardet');
              }
              if (encoding == null) {
                encoding = (_ref3 = jschardet.detect(buffer)) != null ? _ref3.encoding : void 0;
              }
            }
            encoding || (encoding = 'utf8');
            if (docpadUtil.isStandardEncoding(encoding) === false) {
              try {
                if (encodingUtil == null) {
                  encodingUtil = require('encoding');
                }
              } catch (_error) {
                err = _error;
              }
              if (encodingUtil != null) {
                this.log('info', "Converting encoding " + encoding + " to UTF-8 on " + relativePath);
                d = require('domain').create();
                d.on('error', function() {
                  return _this.log('warn', "Encoding conversion failed, therefore we cannot convert the encoding " + encoding + " to UTF-8 on " + relativePath);
                });
                d.run(function() {
                  return buffer = encodingUtil.convert(buffer, 'utf8', encoding);
                });
              } else {
                this.log('warn', "Encoding utilities did not load, therefore we cannot convert the encoding " + encoding + " to UTF-8 on " + relativePath);
              }
            }
            changes.encoding = encoding;
          } else {
            encoding = changes.encoding = 'binary';
          }
        }
        if (encoding === 'binary') {
          content = source = '';
          changes.content = content;
          changes.source = source;
        } else {
          if ((encoding != null) === false) {
            encoding = changes.encoding = 'utf8';
          }
          source = (buffer != null ? buffer.toString('utf8') : void 0) || '';
          content = source;
          changes.content = content;
          changes.source = source;
        }
        this.set(changes);
        next();
        return this;
      };
  
      FileModel.prototype.normalize = function(opts, next) {
        var basename, changes, contentType, ctime, date, err, extension, extensions, filename, fullDirPath, fullPath, meta, mtime, name, outBasename, outContentType, outDirPath, outExtension, outFilename, outPath, relativeBase, relativeDirPath, relativeOutBase, relativeOutDirPath, relativeOutPath, relativePath, rtime, slug, tags, url, wtime, _defaultUrl, _ref2;
        if (opts == null) {
          opts = {};
        }
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        changes = {};
        meta = this.getMeta();
        filename = opts.filename || this.get('filename') || null;
        relativePath = opts.relativePath || this.get('relativePath') || null;
        fullPath = opts.fullPath || this.get('fullPath') || null;
        mtime = opts.mtime || this.get('mtime') || null;
        tags = opts.tags || meta.get('tags') || null;
        date = opts.date || meta.get('date') || null;
        name = opts.name || meta.get('name') || null;
        slug = opts.slug || meta.get('slug') || null;
        url = opts.url || meta.get('url') || null;
        contentType = opts.contentType || meta.get('contentType') || null;
        outContentType = opts.outContentType || meta.get('outContentType') || null;
        outFilename = opts.outFilename || meta.get('outFilename') || null;
        outExtension = opts.outExtension || meta.get('outExtension') || null;
        outPath = opts.outPath || meta.get('outPath') || null;
        extensions = null;
        extension = null;
        basename = null;
        outBasename = null;
        relativeOutPath = null;
        relativeDirPath = null;
        relativeOutDirPath = null;
        relativeBase = null;
        relativeOutBase = null;
        outDirPath = null;
        fullDirPath = null;
        changes.filename = filename = this.getFilename({
          filename: filename,
          relativePath: relativePath,
          fullPath: fullPath
        });
        if (!filename) {
          err = new Error('filename is required, it can be specified via filename, fullPath, or relativePath');
          return next(err);
        }
        if (!relativePath && filename) {
          changes.relativePath = relativePath = filename;
        }
        changes.basename = basename = docpadUtil.getBasename(filename);
        changes.extensions = extensions = this.getExtensions({
          filename: filename
        });
        changes.extension = extension = docpadUtil.getExtension(extensions);
        if (fullPath) {
          changes.fullDirPath = fullDirPath = docpadUtil.getDirPath(fullPath);
        }
        changes.relativeDirPath = relativeDirPath = docpadUtil.getDirPath(relativePath);
        changes.relativeBase = relativeBase = relativeDirPath ? pathUtil.join(relativeDirPath, basename) : basename;
        if (!contentType) {
          changes.contentType = contentType = mime.lookup(fullPath || relativePath);
        }
        if (tags && typeChecker.isArray(tags) === false) {
          changes.tags = tags = String(tags).split(/[\s,]+/);
        }
        if (!date) {
          changes.date = date = mtime || this.get('date') || new Date();
        }
        if (!outFilename && !outPath) {
          changes.outFilename = outFilename = docpadUtil.getOutFilename(basename, outExtension || extensions.join('.'));
        }
        if (!outPath) {
          changes.outPath = outPath = this.rootOutDirPath ? pathUtil.resolve(this.rootOutDirPath, relativeDirPath, outFilename) : null;
        }
        if (outPath) {
          changes.outFilename = outFilename = docpadUtil.getFilename(outPath);
        }
        changes.outDirPath = outDirPath = outPath ? docpadUtil.getDirPath(outPath) : null;
        changes.outBasename = outBasename = docpadUtil.getBasename(outFilename);
        changes.outExtension = outExtension = docpadUtil.getExtension(outFilename);
        changes.relativeOutPath = relativeOutPath = outPath ? outPath.replace(this.rootOutDirPath, '').replace(/^[\/\\]/, '') : pathUtil.join(relativeDirPath, outFilename);
        changes.relativeOutDirPath = relativeOutDirPath = docpadUtil.getDirPath(relativeOutPath);
        changes.relativeOutBase = relativeOutBase = pathUtil.join(relativeOutDirPath, outBasename);
        if (!name) {
          changes.name = name = outFilename;
        }
        _defaultUrl = docpadUtil.getUrl(relativeOutPath);
        if (url) {
          this.setUrl(url);
          this.addUrl(_defaultUrl);
        } else {
          this.setUrl(_defaultUrl);
        }
        if (!outContentType && contentType) {
          changes.outContentType = outContentType = mime.lookup(outPath || relativeOutPath) || contentType;
        }
        if (!slug) {
          changes.slug = slug = docpadUtil.getSlug(relativeOutBase);
        }
        if (typeof wtime === 'string') {
          changes.wtime = wtime = new Date(wtime);
        }
        if (typeof rtime === 'string') {
          changes.rtime = rtime = new Date(rtime);
        }
        if (typeof ctime === 'string') {
          changes.ctime = ctime = new Date(ctime);
        }
        if (typeof mtime === 'string') {
          changes.mtime = mtime = new Date(mtime);
        }
        if (typeof date === 'string') {
          changes.date = date = new Date(date);
        }
        this.set(changes);
        next();
        return this;
      };
  
      FileModel.prototype.contextualize = function(opts, next) {
        var _ref2;
        if (opts == null) {
          opts = {};
        }
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        next();
        return this;
      };
  
      FileModel.prototype.render = function(opts, next) {
        var file, _ref2;
        if (opts == null) {
          opts = {};
        }
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        file.attributes.rtime = new Date();
        next(null, file.getOutContent(), file);
        return this;
      };
  
      FileModel.prototype.write = function(opts, next) {
        var err, file, _ref2, _ref3;
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        opts.path || (opts.path = file.get('outPath'));
        opts.encoding || (opts.encoding = file.get('encoding') || 'utf8');
        opts.content || (opts.content = file.getOutContent());
        opts.type || (opts.type = 'out file');
        if (!opts.path) {
          next();
          return this;
        }
        if ((_ref3 = opts.encoding.toLowerCase()) !== 'ascii' && _ref3 !== 'utf8' && _ref3 !== 'utf-8' && _ref3 !== 'binary') {
          try {
            if (encodingUtil == null) {
              encodingUtil = require('encoding');
            }
          } catch (_error) {
            err = _error;
          }
          if (encodingUtil != null) {
            this.log('info', "Converting encoding UTF-8 to " + opts.encoding + " on " + opts.path);
            try {
              opts.content = encodingUtil.convert(opts.content, opts.encoding, 'utf8');
            } catch (_error) {
              err = _error;
              this.log('warn', "Encoding conversion failed, therefore we cannot convert the encoding UTF-8 to " + opts.encoding + " on " + opts.path);
            }
          } else {
            this.log('warn', "Encoding utilities did not load, therefore we cannot convert the encoding UTF-8 to " + opts.encoding + " on " + opts.path);
          }
        }
        file.log('debug', "Writing the " + opts.type + ": " + opts.path + " " + opts.encoding);
        safefs.writeFile(opts.path, opts.content, function(err) {
          if (err) {
            return next(err);
          }
          if (opts.type === 'out file') {
            file.attributes.wtime = new Date();
          }
          file.log('debug', "Wrote the " + opts.type + ": " + opts.path + " " + opts.encoding);
          return next();
        });
        return this;
      };
  
      FileModel.prototype.writeSource = function(opts, next) {
        var file, _ref2;
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        opts.path || (opts.path = file.get('fullPath'));
        opts.content || (opts.content = (file.getContent() || '').toString(''));
        opts.type || (opts.type = 'source file');
        this.write(opts, next);
        return this;
      };
  
      FileModel.prototype['delete'] = function(opts, next) {
        var file, _ref2;
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        opts.path || (opts.path = file.get('outPath'));
        opts.type || (opts.type = 'out file');
        if (!opts.path) {
          next();
          return this;
        }
        file.log('debug', "Delete the " + opts.type + ": " + opts.path);
        safefs.exists(opts.path, function(exists) {
          if (!exists) {
            return next();
          }
          return safefs.unlink(opts.path, function(err) {
            if (err) {
              return next(err);
            }
            file.log('debug', "Deleted the " + opts.type + ": " + opts.path);
            return next();
          });
        });
        return this;
      };
  
      FileModel.prototype.deleteSource = function(opts, next) {
        var file, _ref2;
        _ref2 = extractOptsAndCallback(opts, next), opts = _ref2[0], next = _ref2[1];
        file = this;
        opts.path || (opts.path = file.get('fullPath'));
        opts.type || (opts.type = 'source file');
        this["delete"](opts, next);
        return this;
      };
  
      return FileModel;
  
    })(Model);
  
    module.exports = FileModel;
  
  }).call(this);
  