{"action":"created","comment":{"url":"https://api.github.com/repos/saimonmoore/snockets/pulls/comments/76609479","id":76609479,"diff_hunk":"@@ -1,693 +1,511 @@\n-# vim:expandtab ts=2 sw=2\n-# [snockets](http://github.com/TrevorBurnham/snockets)\n+# [snockets](http://github.com/pthrasher/snockets)\n \n DepGraph = require 'dep-graph'\n-SourceMap = require 'source-map'\n-\n-CoffeeScript = require 'coffee-script'\n fs           = require 'fs'\n path         = require 'path'\n-uglify       = require 'uglify-js'\n _            = require 'underscore'\n \n-module.exports = class Snockets\n-  constructor: (@options = {}) ->\n-    @options.srcmap ?= false\n-    @options.target ?= null\n-    @options.staticRoot ?= null\n-    @options.staticRootUrl ?= '/'\n-    @options.src ?= '.'\n-    @options.async ?= true\n-    @cache = {}\n-    @concatCache = {}\n-    @depGraph = new DepGraph\n-    @logLevels = [\n-      'info'\n-      'warn'\n-      'debug'\n-      'error'\n-    ]\n-\n-    # If the user wants srcmaps, we need to know a few other things first in\n-    # order to adequately fill out info within them. If this info isn't\n-    # provided, we cannot proceed.\n-    if @options.srcmap\n-      unless @options.staticRoot? or @options.target?\n-        if not @options.staticRoot? and not @options.target?\n-          errorStr = 'both of the options \\'staticRoot\\' and \\'target\\''\n-        else if @options.staticRoot? and not @options.target?\n-          errorStr = '\\'target\\' option'\n-        else if not @options.staticRoot? and @options.target?\n-          errorStr = '\\'staticRoot\\' option'\n-        throw new Error(\"When generating source maps\n-                         #{errorStr} must be provided.\")\n-\n-  # ## Logging methods\n-  log: (args, level) ->\n-    if _.contains(@logLevels, level)\n-      console.log.apply console, args\n-\n-  info: (args...) => @log args, 'info'\n-  warn: (args...) => @log args, 'warn'\n-  debug: (args...) => @log args, 'debug'\n-  error: (args...) => @log args, 'error'\n-\n-  # ## Public methods\n-\n-  scan: (filePath, flags, callback) ->\n-    if typeof flags is 'function'\n-      callback = flags; flags = {}\n-    flags ?= {}\n-    flags.async ?= @options.async\n-\n-    @updateDirectives filePath, flags, (err, graphChanged) =>\n-      if err\n-        if callback then return callback err else throw err\n-      callback? null, @depGraph, graphChanged\n-      @depGraph\n-\n-  getCompiledChain: (filePath, flags, callback) ->\n-    if typeof flags is 'function'\n-      callback = flags; flags = {}\n-    flags ?= {}\n-    flags.async ?= @options.async\n-\n-    @updateDirectives filePath, flags, (err, graphChanged) =>\n-      if err\n-        if callback then return callback err else throw err\n-      try\n-        chain = @depGraph.getChain filePath\n-      catch e\n-        if callback then return callback e else throw e\n-\n-      compiledChain = for link in chain.concat filePath\n-        o = {}\n-        if @compileFile link\n-          o.filename = stripExt(link) + '.js'\n-        else\n-          o.filename = link\n-        o.js = @cache[link].js.toString 'utf8'\n-        o\n-\n-      callback? null, compiledChain, graphChanged\n-      compiledChain\n-\n-  getConcatenation: (filePath, flags, callback) ->\n-    if typeof flags is 'function'\n-      callback = flags; flags = {}\n-    flags ?= {}\n-    flags.async ?= @options.async\n-    concatenationChanged = true\n-\n-    @updateDirectives filePath, flags, (err, graphChanged) =>\n-      # fail fast\n-      if err\n-        if callback then return callback err else throw err\n-\n-      doSrcMap = @options.srcmap\n-      doMinify = flags.minify\n-      if doSrcMap and not doMinify\n-        # we can't do srcmaps without minification reliably.\n-        # TODO: We *can* do this if every src in the chain is coffeescript, or\n-        #       another transpiled language that supports source maps. However,\n-        #       if some of the source is javascript, or the language doesn't\n-        #       support generating source maps, we cannot reliably create\n-        #       concatenated files that map properly. Or any source maps in the\n-        #       chain are missing, we don't have a simple way of doing this.\n-        #\n-        #       UPDATE: The real bug is that the line numbers are off when we\n-        #               don't have source maps for the non-compiled /\n-        #               non-minified files. The only time source maps work is\n-        #               with minification. I added a fix for the line numbers,\n-        #               but it appears to need tweaking.\n-        doSrcMap = false\n-        @warn \"Disabling srcmap generation due to no minification. [#{filePath}]\"\n-\n-\n-      # create the placeholder if it doesn't exist already.\n-      unless @concatCache[filePath]?\n-        @concatCache[filePath] = {}\n-\n-      # Don't trust the cache\n-      cacheValid = false\n-      hasData    = @concatCache[filePath].data?\n-      hasMinData = @concatCache[filePath].minifiedData?\n-      hasSrcMap  = @concatCache[filePath].srcmap?\n-\n-      # Attempt to validate the cache.\n-      if not (doSrcMap and doMinify) # not srcmapping, not minifying\n-        cacheValid = true if hasData\n-      if not doSrcMap and doMinify # not srcmapping, minifying\n-        cacheValid = true if hasMinData\n-      if doSrcMap and doMinify # we're srcmapping and minifying\n-        cacheValid = true if hasSrcMap and hasMinData\n-\n-      # We should now have a rough, early overview as to whether or not the\n-      # cache is valid, as well as what sorts of things need to be generated\n-      # below.\n-\n-      try\n-        if cacheValid and not doMinify\n-          # We have a valid cache, and we're not minifying.\n-          concatenation = @concatCache[filePath].data.toString 'utf8'\n-          concatenationChanged = false\n-        else if cacheValid and doMinify and not doSrcMap\n-          concatenation = @concatCache[filePath].minifiedData.toString 'utf8'\n-          concatenationChanged = false\n-        else if cacheValid and doMinify and doSrcMap\n-          js = @concatCache[filePath].minifiedData.toString 'utf8'\n-          srcmap = @concatCache[filePath].srcmap\n-          concatenation = {\n-            js\n-            srcmap\n-          }\n-          concatenationChanged = false\n-        else\n-          @concatCache[filePath].maps = {}\n-\n-          # append the src file to the end of it's own dependency list.\n-          chain = @depGraph.getChain(filePath).concat filePath\n-\n-          cacheMiss = false # keep track of whether or not anything was regenerated.\n-\n-          sources = []\n-          for link in chain\n-            isCompiled = @compileFile link\n-\n-            cached = @cache[link] # get a reference to the cache.\n \n-            # TODO: Find out what could possibly cause a file to not be cached\n-            #       at this point..\n-            continue unless cached?\n-\n-            _hasJs      = cached.js?\n-            _hasMinData = cached.minifiedData?\n-            _hasSrcMap  = cached.srcmap?\n-\n-            _cacheValid = false\n-            if not doMinify\n-              _cacheValid = if _hasJs then true else false\n+{ parseDirectives, HoldingQueue\n+    timeEq, getUrlPath\n+    sourceMapCat, EXPLICIT_PATH\n+    DIRECTIVE, HEADER } = require './util'\n+{ compilers, jsExts\n+    stripExt }          = require './compilers'\n+{ minify }              = require './minification'\n+\n+\n+class Snockets\n+    constructor: (@options = {}) ->\n+        @options.srcmap ?= false\n+        @options.target ?= null\n+        @options.staticRoot ?= null\n+        @options.staticRootUrl ?= '/'\n+        @options.src ?= '.'\n+        @options.async ?= true\n+        @cache = {}\n+        @concatCache = {}\n+        @depGraph = new DepGraph\n+        @logLevels = [\n+            'info'\n+            'warn'\n+            'debug'\n+            'error'\n+        ]\n+\n+        # If the user wants srcmaps, we need to know a few other things first in\n+        # order to adequately fill out info within them. If this info isn't\n+        # provided, we cannot proceed.\n+        if @options.srcmap\n+            unless @options.staticRoot? or @options.target?\n+                if not @options.staticRoot? and not @options.target?\n+                    errorStr = \"both of the options 'staticRoot' and 'target'\"\n+                else if @options.staticRoot? and not @options.target?\n+                    errorStr = \"'target' option\"\n+                else if not @options.staticRoot? and @options.target?\n+                    errorStr = \"'staticRoot' option\"\n+                throw new Error(\"When generating source maps\n+                                                 #{errorStr} must be provided.\")\n+\n+    # ## Logging methods\n+    log: (args, level) ->\n+        if _.contains(@logLevels, level)\n+            console.log.apply console, args\n+\n+    info: (args...) => @log args, 'info'\n+    warn: (args...) => @log args, 'warn'\n+    debug: (args...) => @log args, 'debug'\n+    error: (args...) => @log args, 'error'\n+\n+    # ## Public methods\n+\n+    scan: (filePath, flags, callback) ->\n+        if typeof flags is 'function'\n+            callback = flags; flags = {}\n+        flags ?= {}\n+        flags.async ?= @options.async\n+\n+        @updateDirectives filePath, flags, {}, (err, graphChanged) =>\n+            if err\n+                if callback then return callback err else throw err\n+            callback? null, @depGraph, graphChanged\n+            @depGraph\n+\n+    getCompiledChain: (filePath, flags, callback) ->\n+        if typeof flags is 'function'\n+            callback = flags; flags = {}\n+        flags ?= {}\n+        flags.async ?= @options.async\n+\n+        @updateDirectives filePath, flags, {}, (err, graphChanged) =>\n+            if err\n+                if callback then return callback err else throw err\n+            try\n+                chain = @depGraph.getChain filePath\n+            catch e\n+                if callback then return callback e else throw e\n+\n+            compiledChain = for link in chain.concat filePath\n+                o = {}\n+                if @compileFile link\n+                    o.filename = stripExt(link) + '.js'\n+                else\n+                    o.filename = link\n+                o.js = @cache[link].js.toString 'utf8'\n+                o\n+\n+            callback? null, compiledChain, graphChanged\n+            compiledChain\n+\n+    getConcatenation: (filePath, flags, callback) ->\n+        if typeof flags is 'function'\n+            callback = flags; flags = {}\n+        flags ?= {}\n+        flags.async ?= @options.async\n+        concatenationChanged = true\n+\n+        @updateDirectives filePath, flags, {}, (err, graphChanged) =>\n+            # fail fast\n+            if err\n+                if callback then return callback err else throw err\n+                return\n+\n+            doSrcMap = @options.srcmap\n+            doMinify = flags.minify\n+            if doSrcMap and not doMinify\n+                # we can't do srcmaps without minification reliably.\n+                # TODO: We *can* do this if every src in the chain is\n+                #       coffeescript, or another transpiled language that\n+                #       supports source maps. However, if some of the source is\n+                #       javascript, or the language doesn't support generating\n+                #       source maps, we cannot reliably create concatenated\n+                #       files that map properly. Or any source maps in the\n+                #       chain are missing, we don't have a simple way of doing\n+                #       this.\n+                #\n+                # UPDATE: The real bug is that the line numbers are off when we\n+                #       don't have source maps for the non-compiled /\n+                #       non-minified files. The only time source maps work is\n+                #       with minification. I added a fix for the line numbers,\n+                #       but it appears to need tweaking.\n+                doSrcMap = false\n+                @warn \"Disabling srcmap generation\n+                    due to no minification. [#{filePath}]\"\n+\n+\n+            # create the placeholder if it doesn't exist already.\n+            unless @concatCache[filePath]?\n+                @concatCache[filePath] = {}\n+\n+            # Don't trust the cache\n+            cacheValid = false\n+            hasData        = @concatCache[filePath].data?\n+            hasMinData = @concatCache[filePath].minifiedData?\n+            hasSrcMap    = @concatCache[filePath].srcmap?\n+\n+            # Attempt to validate the cache.\n+            if not (doSrcMap or doMinify) # not srcmapping, not minifying\n+                cacheValid = true if hasData\n             if not doSrcMap and doMinify # not srcmapping, minifying\n-              _cacheValid = if _hasMinData then true else false\n-            if doSrcMap and not doMinify # we're srcmapping and not minifying\n-              _cacheValid = if _hasSrcMap and _hasJs then true else false\n+                cacheValid = if hasMinData then true else false\n             if doSrcMap and doMinify # we're srcmapping and minifying\n-              _cacheValid = if _hasSrcMap and _hasMinData then true else false\n-\n-            if _cacheValid and not doMinify and not doSrcMap\n-              sources.push cached.js.toString 'utf8'\n-            else if _cacheValid and doMinify and not doSrcMap\n-              sources.push cached.minifiedData.toString 'utf8'\n-            else if _cacheValid and doMinify and doSrcMap\n-              sources.push {\n-                js: cached.minifiedData.toString 'utf8'\n-                srcmap: cached.srcmap\n-              }\n-            else if _cacheValid and not doMinify and doSrcMap\n-              js = cached.js.toString 'utf8'\n-              unless cached.srcmap?\n-                numLines = js.split(/\\r\\n|\\r|\\n/gm).length\n-                cached.srcmap =\n-                    empty: true\n-                    numLines: numLines\n-                    file: link\n-\n-              sources.push {\n-                js: js\n-                srcmap: cached.srcmap\n-              }\n-            else\n-              # CACHE MISS\n-              # Do minification / sourcemapping\n-              cacheMiss = true\n-              _srcmap = null\n-              _mindata = null\n-\n-              minopts = {}\n-              if doSrcMap\n-                absLink = path.resolve @options.src, link\n-                minopts.outname = \"#{stripExt(absLink)}.js\"\n-                minopts.srcmap = true\n-                minopts.inname = absLink\n-                minopts.staticRoot = @options.staticRoot\n-                minopts.staticRootUrl = @options.staticRootUrl\n-\n-              if isCompiled and _hasSrcMap and doSrcMap\n-                # pass existing srcmap to minifier.\n-                minopts.srcmap = cached.srcmap\n-\n-              toMinify = cached.js.toString 'utf8'\n-\n-              if doMinify\n-                result = minify toMinify, minopts\n-              else\n-                if doSrcMap\n-                  if isCompiled\n-                    result =\n-                      srcmap: cached.srcmap\n-                      js: toMinify\n-                  else\n-                    numLines = toMinify.split(/\\r\\n|\\r|\\n/gm).length\n-                    result =\n-                      srcmap:\n-                        empty: true\n-                        numLines: numLines\n-                        file: link\n-                      js: toMinify\n+                cacheValid = true if hasSrcMap and hasMinData\n+\n+            # We should now have a rough, early overview as to whether or not\n+            # the cache is valid, as well as what sorts of things need to be\n+            # generated below.\n+\n+            try\n+                if cacheValid and not doMinify\n+                    # We have a valid cache, and we're not minifying.\n+                    concatenation = @concatCache[filePath].data.toString 'utf8'\n+                    concatenationChanged = false\n+                else if cacheValid and doMinify and not doSrcMap\n+                    concatenation = @concatCache[filePath]\n+                        .minifiedData.toString 'utf8'\n+                    concatenationChanged = false\n+                else if cacheValid and doMinify and doSrcMap\n+                    js = @concatCache[filePath].minifiedData.toString 'utf8'\n+                    srcmap = @concatCache[filePath].srcmap\n+                    concatenation = {\n+                        js\n+                        srcmap\n+                    }\n+                    concatenationChanged = false\n                 else\n-                  result = toMinify\n-\n-              if doSrcMap\n-                _srcmap = result.srcmap\n-                _mindata = new Buffer result.js\n-                sources.push {\n-                  srcmap: _srcmap\n-                  js: result.js\n-                }\n-              else\n-                _mindata = new Buffer result\n-                sources.push result\n-\n-\n-              cached.minifiedData = _mindata\n-              cached.srcmap = _srcmap\n-\n-\n-          if cacheMiss\n-            concatenationChanged = true\n-          else\n-            concatenationChanged = false\n-\n-          # Concatenate the aggregated sources\n-          if not doSrcMap\n-            concatenation = sources.join '\\n'\n-          else\n-            # We have to concatenate the source maps alongside the sources\n-            _sources = _.pluck sources, 'js'\n-            _maps    = _.pluck sources, 'srcmap'\n-\n-            catjs = _sources.join '\\n'\n-            targetUrl = getUrlPath @options.target, @options.staticRoot, @options.staticRootUrl\n-            catmaps = sourceMapCat\n-              filename: targetUrl\n-              maps: _maps\n-\n-            concatenation =\n-              js: catjs\n-              srcmap: catmaps\n-      catch e\n-        if callback then return callback e else throw e\n-\n-      if not (doMinify and doSrcMap)\n-        @concatCache[filePath].data = new Buffer concatenation\n-      else if doMinify and not doSrcMap\n-        @concatCache[filePath].minifiedData = new Buffer concatenation\n-      else if doMinify and doSrcMap\n-        @concatCache[filePath].minifiedData = new Buffer concatenation.js\n-        @concatCache[filePath].srcmap = concatenation.srcmap\n-      else if not doMinify and doSrcMap\n-        @concatCache[filePath].data = new Buffer concatenation.js\n-        @concatCache[filePath].srcmap = concatenation.srcmap\n-\n-      callback? null, concatenation, concatenationChanged\n-      concatenation\n+                    @concatCache[filePath].maps = {}\n+\n+                    # append the src file to the end of it's own dependency list\n+                    chain = @depGraph.getChain(filePath).concat filePath\n+\n+                    # keep track of whether or not anything was regenerated.\n+                    cacheMiss = false\n+\n+                    sources = []\n+                    for link in chain\n+                        isCompiled = @compileFile link\n+\n+                        cached = @cache[link] # get a reference to the cache.\n+\n+                        # TODO: Find out what could possibly cause a file to\n+                        #       not be cached at this point..\n+                        continue unless cached?\n+\n+                        _hasJs            = cached.js?\n+                        _hasMinData = cached.minifiedData?\n+                        _hasSrcMap    = cached.srcmap?\n+\n+                        _cacheValid = false\n+                        if not doMinify\n+                            _cacheValid =\n+                                if _hasJs then true else false\n+                        if not doSrcMap and doMinify\n+                            # not srcmapping, minifying\n+                            _cacheValid =\n+                                if _hasMinData then true else false\n+                        if doSrcMap and not doMinify\n+                            # we're srcmapping and not minifying\n+                            _cacheValid =\n+                                if _hasSrcMap and _hasJs then true else false\n+                        if doSrcMap and doMinify\n+                            # we're srcmapping and minifying\n+                            if _hasSrcMap and _hasMinData\n+                                _cacheValid = true\n+                            else\n+                                false\n+\n+                        if _cacheValid and not doMinify and not doSrcMap\n+                            sources.push cached.js.toString 'utf8'\n+                        else if _cacheValid and doMinify and not doSrcMap\n+                            sources.push cached.minifiedData.toString 'utf8'\n+                        else if _cacheValid and doMinify and doSrcMap\n+                            sources.push {\n+                                js: cached.minifiedData.toString 'utf8'\n+                                srcmap: cached.srcmap\n+                            }\n+                        else if _cacheValid and not doMinify and doSrcMap\n+                            js = cached.js.toString 'utf8'\n+                            unless cached.srcmap?\n+                                numLines = js.split(/\\r\\n|\\r|\\n/gm).length\n+                                cached.srcmap =\n+                                        empty: true\n+                                        numLines: numLines\n+                                        file: link\n+\n+                            sources.push {\n+                                js: js\n+                                srcmap: cached.srcmap\n+                            }\n+                        else\n+                            # CACHE MISS\n+                            # Do minification / sourcemapping\n+                            cacheMiss = true\n+                            _srcmap = null\n+                            _mindata = null\n+\n+                            minopts = {}\n+                            if doSrcMap\n+                                absLink = path.resolve @options.src, link\n+                                minopts.outname = \"#{stripExt(absLink)}.js\"\n+                                minopts.srcmap = true\n+                                minopts.inname = absLink\n+                                minopts.staticRoot = @options.staticRoot\n+                                minopts.staticRootUrl = @options.staticRootUrl\n+\n+                            if isCompiled and _hasSrcMap and doSrcMap\n+                                # pass existing srcmap to minifier.\n+                                minopts.srcmap = cached.srcmap\n+\n+                            toMinify = cached.js.toString 'utf8'\n+\n+                            if doMinify\n+                                result = minify toMinify, minopts\n+                            else\n+                                if doSrcMap\n+                                    if isCompiled\n+                                        result =\n+                                            srcmap: cached.srcmap\n+                                            js: toMinify\n+                                    else\n+                                        numLines = toMinify\n+                                            .split(/\\r\\n|\\r|\\n/gm).length\n+                                        result =\n+                                            srcmap:\n+                                                empty: true\n+                                                numLines: numLines\n+                                                file: link\n+                                            js: toMinify\n+                                else\n+                                    result = toMinify\n+\n+                            if doSrcMap\n+                                _srcmap = result.srcmap\n+                                _mindata = new Buffer result.js\n+                                sources.push {\n+                                    srcmap: _srcmap\n+                                    js: result.js\n+                                }\n+                            else\n+                                _mindata = new Buffer result\n+                                sources.push result\n+\n+\n+                            cached.minifiedData = _mindata\n+                            cached.srcmap = _srcmap\n+\n+\n+                    if cacheMiss\n+                        concatenationChanged = true\n+                    else\n+                        concatenationChanged = false\n+\n+                    # Concatenate the aggregated sources\n+                    if not doSrcMap\n+                        concatenation = sources.join '\\n'\n+                    else\n+                        # We have to concatenate the source maps alongside the\n+                        # sources\n+                        _sources = _.pluck sources, 'js'\n+                        _maps        = _.pluck sources, 'srcmap'\n+\n+                        catjs = _sources.join '\\n'\n+                        targetUrl = getUrlPath @options.target,\n+                            @options.staticRoot, @options.staticRootUrl\n+                        catmaps = sourceMapCat\n+                            filename: targetUrl\n+                            maps: _maps\n+\n+                        concatenation =\n+                            js: catjs\n+                            srcmap: catmaps\n+            catch _err\n+                throw _err\n+                # if callback then return callback _err else throw _err\n+                return\n+\n+            if not (doMinify or doSrcMap)\n+                @concatCache[filePath].data = new Buffer concatenation\n+            else if doMinify and not doSrcMap\n+                @concatCache[filePath].minifiedData = new Buffer concatenation\n+            else if doMinify and doSrcMap\n+                @concatCache[filePath].minifiedData =\n+                    new Buffer concatenation.js\n+                @concatCache[filePath].srcmap = concatenation.srcmap\n+            else if not doMinify and doSrcMap\n+                @concatCache[filePath].data = new Buffer concatenation.js\n+                @concatCache[filePath].srcmap = concatenation.srcmap\n+\n+            callback? null, concatenation, concatenationChanged\n+            concatenation\n \n   # ## Internal methods\n \n   # Interprets the directives from the given file to update `@depGraph`.\n-  updateDirectives: (filePath, flags, excludes..., callback) ->\n-    return callback() if filePath in excludes\n-    excludes.push filePath\n-\n-    depList = []\n-    graphChanged = false\n-    q = new HoldingQueue\n-      task: (depPath, next) =>\n-        return next() unless path.extname(depPath) in jsExts()\n-        if depPath is filePath\n-          err = new Error(\"Script tries to require itself: #{filePath}\")\n-          return callback err\n-        unless depPath in depList\n-          depList.push depPath\n-        @updateDirectives depPath, flags, excludes..., (err, depChanged) ->\n-          return callback err if err\n-          graphChanged or= depChanged\n-          next()\n-      onComplete: =>\n-        unless _.isEqual depList , @depGraph.map[filePath]\n-          @depGraph.map[filePath] = depList\n-          graphChanged = true\n-        if graphChanged\n-          @concatCache[filePath] = null\n-        callback null, graphChanged\n-\n-    require = (relPath) =>\n-      q.waitFor relName = stripExt relPath\n-      if relName.match EXPLICIT_PATH\n-        depPath = relName + '.js'\n-        q.perform relName, depPath\n-      else\n-        depName = @joinPath path.dirname(filePath), relName\n-        @findMatchingFile depName, flags, (err, depPath) ->\n-          return callback err if err\n-          q.perform relName, depPath\n-\n-    requireTree = (dirName) =>\n-      q.waitFor dirName\n-      @readdir @absPath(dirName), flags, (err, items) =>\n-        return callback err if err\n-        q.unwaitFor dirName\n-        for item in items\n-          itemPath = @joinPath dirName, item\n-          continue if @absPath(itemPath) is @absPath(filePath)\n-          q.waitFor itemPath\n-          do (itemPath) =>\n-            @stat @absPath(itemPath), flags, (err, stats) =>\n-              return callback err if err\n-              if stats.isFile()\n-                q.perform itemPath, itemPath\n-              else\n-                requireTree itemPath\n-                q.unwaitFor itemPath\n-\n-    @readFile filePath, flags, (err, fileChanged) =>\n-      return callback err if err\n-      if fileChanged then graphChanged = true\n-      for directive in parseDirectives(@cache[filePath].data.toString 'utf8')\n-        words = directive.replace(/['\"]/g, '').split /\\s+/\n-        [command, relPaths...] = words\n-\n-        switch command\n-          when 'require'\n-            require relPath for relPath in relPaths\n-          when 'require_tree'\n-            for relPath in relPaths\n-              requireTree @joinPath path.dirname(filePath), relPath\n-\n-      q.finalize()\n-\n-  # Searches for a file with the given name (no extension, e.g. `'foo/bar'`)\n-  findMatchingFile: (filename, flags, callback) ->\n-    tryFiles = (filePaths) =>\n-      for filePath in filePaths\n-        if stripExt(@absPath filePath) is @absPath(filename)\n-          callback null, filePath\n-          return true\n-\n-    return if tryFiles _.keys @cache\n-    @readdir path.dirname(@absPath filename), flags, (err, files) =>\n-      return callback err if err\n-      return if tryFiles (for file in files\n-        @joinPath path.dirname(filename), file\n-      )\n-      callback new Error(\"File not found: '#{filename}'\")\n-\n-  # Wrapper around fs.readdir or fs.readdirSync, depending on flags.async.\n-  readdir: (dir, flags, callback) ->\n-    if flags.async\n-      fs.readdir @absPath(dir), callback\n-    else\n-      try\n-        files = fs.readdirSync @absPath(dir)\n-        callback null, files\n-      catch e\n-        callback e\n-\n-  # Wrapper around fs.stat or fs.statSync, depending on flags.async.\n-  stat: (filePath, flags, callback) ->\n-    if flags.async\n-      fs.stat @absPath(filePath), callback\n-    else\n-      try\n-        stats = fs.statSync @absPath(filePath)\n-        callback null, stats\n-      catch e\n-        callback e\n-\n-  # Reads a file's data and timestamp into the cache.\n-  readFile: (filePath, flags, callback) ->\n-    @stat filePath, flags, (err, stats) =>\n-      return callback err if err\n-      if timeEq @cache[filePath]?.mtime, stats.mtime\n-        return callback null, false\n-      if flags.async\n-          fs.readFile @absPath(filePath), (err, data) =>\n+    updateDirectives: (filePath, flags, excludes, callback) ->\n+        return callback() if excludes[filePath]\n+        excludes[filePath] = 1\n+\n+        depList = []\n+        graphChanged = false\n+        q = new HoldingQueue\n+            task: (depPath, next) =>\n+                return next() unless path.extname(depPath) in jsExts()\n+                if depPath is filePath\n+                    err = new Error(\"Script tries to require\n+                        itself: #{filePath}\")\n+                    return callback err\n+                unless depPath in depList\n+                    depList.push depPath\n+                @updateDirectives depPath, flags, excludes, (err, depChanged) ->\n+                    return callback err if err\n+                    graphChanged or= depChanged\n+                    next()\n+            onComplete: =>\n+                unless _.isEqual depList , @depGraph.map[filePath]\n+                    @depGraph.map[filePath] = depList\n+                    graphChanged = true\n+                if graphChanged\n+                    @concatCache[filePath] = null\n+                callback null, graphChanged\n+\n+        require = (relPath) =>\n+            q.waitFor relName = stripExt relPath\n+            if relName.match EXPLICIT_PATH\n+                depPath = relName + '.js'\n+                q.perform relName, depPath\n+            else\n+                depName = @joinPath path.dirname(filePath), relName\n+                @findMatchingFile depName, flags, (err, depPath) ->\n+                    return callback err if err\n+                    q.perform relName, depPath\n+\n+        requireTree = (dirName) =>\n+            q.waitFor dirName\n+            @readdir @absPath(dirName), flags, (err, items) =>\n+                return callback err if err\n+                q.unwaitFor dirName\n+                for item in items\n+                    itemPath = @joinPath dirName, item\n+                    continue if @absPath(itemPath) is @absPath(filePath)\n+                    q.waitFor itemPath\n+                    do (itemPath) =>\n+                        @stat @absPath(itemPath), flags, (err, stats) =>\n+                            return callback err if err\n+                            if stats.isFile()\n+                                q.perform itemPath, itemPath\n+                            else\n+                                requireTree itemPath\n+                                q.unwaitFor itemPath\n+\n+        @readFile filePath, flags, (err, fileChanged) =>\n             return callback err if err\n-            @cache[filePath] = {mtime: stats.mtime, data}\n-            callback null, true\n-      else\n-        try\n-          data = fs.readFileSync @absPath(filePath)\n-          @cache[filePath] = {mtime: stats.mtime, data}\n-          callback null, true\n-        catch e\n-          callback e\n-\n-  compileFile: (filePath) ->\n-    if (ext = path.extname filePath) is '.js'\n-      @cache[filePath].js = @cache[filePath].data\n-      return false\n-    else\n-      src = @cache[filePath].data.toString 'utf8'\n-      pth = @absPath(filePath)\n-      js = compilers[ext[1..]].compileSync @absPath(filePath), src, @options\n-      unless _.isString js\n-        @cache[filePath].srcmap = js.srcmap\n-        js = js.js\n-      @cache[filePath].js = new Buffer(js)\n-      return true\n-\n-  absPath: (relPath) ->\n-    if relPath.match EXPLICIT_PATH\n-      relPath\n-    else if @options.src.match EXPLICIT_PATH\n-      @joinPath @options.src, relPath\n-    else\n-      @joinPath process.cwd(), @options.src, relPath\n-\n-  joinPath: ->\n-    filePath = path.join.apply path, arguments\n-\n-    # Replace backslashes with forward slashes for Windows compatability\n-    if process.platform is 'win32'\n-      slash = '/' # / on the same line as the regex breaks ST2 syntax highlight\n-      filePath.replace /\\\\/g, slash\n-    else\n-      filePath\n-\n-# ## Compilers\n-\n-module.exports.compilers = compilers =\n-  coffee:\n-    match: /\\.js$/\n-    compileSync: (sourcePath, source, useropts = {}) ->\n-      opts =\n-        srcmap: false\n-        staticRoot: ''\n-        staticRootUrl: '/'\n-      _.extend opts, useropts\n-\n-      compileopts =\n-        filename: sourcePath\n-\n-      if opts.srcmap\n-        outname = \"#{sourcePath}.js\"\n-        inname = sourcePath\n-\n-        inurl = getUrlPath inname, opts.staticRoot, opts.staticRootUrl\n-        outurl = getUrlPath outname, opts.staticRoot, opts.staticRootUrl\n-        inbn = path.basename inurl\n-        outbn = path.basename outurl\n-\n-        _.extend compileopts,\n-          filename: outbn\n-          sourceMap: true\n-          generatedFile: \"#{stripExt outurl}.min.js\"\n-          sourceFiles: [inurl]\n-\n-\n-      output = CoffeeScript.compile source, compileopts\n-      if opts.srcmap\n-        srcmap = output.v3SourceMap\n-        if _.isString srcmap\n-          srcmap = JSON.parse srcmap\n-        js = output.js\n-        return { js, srcmap }\n-      output\n-\n-# ## Regexes\n-\n-EXPLICIT_PATH = /^\\/|:/\n-\n-HEADER = ///\n-(?:\n-  (\\#\\#\\# .* \\#\\#\\#\\n*) |\n-  (// .* \\n*) |\n-  (\\# .* \\n*)\n-)+\n-///\n-\n-DIRECTIVE = ///\n-^[\\W] *= \\s* (\\w+.*?) (\\*\\\\/)?$\n-///gm\n-\n-# ## Utility functions\n-\n-class HoldingQueue\n-  constructor: ({@task, @onComplete}) ->\n-    @holdKeys = []\n-  waitFor: (key) ->\n-    @holdKeys.push key\n-  unwaitFor: (key) ->\n-    @holdKeys = _.without @holdKeys, key\n-  perform: (key, args...) ->\n-    @task args..., => @unwaitFor key\n-  finalize: ->\n-    if @holdKeys.length is 0\n-      @onComplete()\n-    else\n-      h = setInterval (=>\n-        if @holdKeys.length is 0\n-          @onComplete()\n-          clearInterval h\n-      ), 10\n-\n-parseDirectives = (code) ->\n-  code = code.replace /[\\r\\t ]+$/gm, '\\n'  # fix for issue #2\n-  return [] unless match = HEADER.exec(code)\n-  header = match[0]\n-  match[1] while match = DIRECTIVE.exec header\n-\n-stripExt = (filePath) ->\n-  if path.extname(filePath) in jsExts()\n-    filePath[0...filePath.lastIndexOf('.')]\n-  else\n-    filePath\n-\n-jsExts = ->\n-  (\".#{ext}\" for ext of compilers).concat '.js'\n-\n-\n-minify = (js, useropts = {}) ->\n-  opts =\n-    mangle: false\n-    srcmap: false\n-    outname: ''\n-    inname: ''\n-    staticRoot: ''\n-    staticRootUrl: '/'\n-\n-  _.extend opts, useropts\n-\n-  parseopts = {}\n-\n-  if opts.inname?\n-    parseopts.filename = opts.inname\n-    if opts.srcmap? and opts.srcmap isnt false\n-\n-      inurl = getUrlPath opts.inname, opts.staticRoot, opts.staticRootUrl\n-      outurl = getUrlPath opts.outname, opts.staticRoot, opts.staticRootUrl\n-      inbn = path.basename inurl\n-      outbn = path.basename outurl\n-\n-      parseopts.filename = inurl\n-\n-  top = uglify.parse js, parseopts\n-  top.figure_out_scope()\n-\n-  # cmpd == compressed\n-  cmpd = top.transform uglify.Compressor\n-    warnings: false\n-  cmpd.figure_out_scope()\n-\n-  if opts.mangle\n-    cmpd.mangle_names()\n-    cmpd.figure_out_scope()\n-\n-  streamopts = {}\n-  if opts.srcmap isnt false\n-\n-    \n-    smopts =\n-      file: \"#{stripExt(outurl)}.min.js\"\n-\n-    if opts.srcmap isnt true\n-      # setting srcmap to true just makes us create an srcmap, otherwise, we're\n-      # passing one in from another compiler.\n-      smopts.orig = opts.srcmap\n-\n-    sm = uglify.SourceMap smopts\n-    streamopts.source_map = sm\n-\n-  stream = uglify.OutputStream streamopts\n-  cmpd.print stream\n-\n-  js = stream.toString()\n-  if opts.srcmap? and opts.srcmap isnt false\n-    srcmap = sm.toString()\n-    if _.isString srcmap\n-      srcmap = JSON.parse srcmap\n-    # TODO: Look into uglify's source to figure out the correct way to get\n-    # uglify to set this for non-compiled scripts\n-    if opts.srcmap is true # Just a standard js file to be minified.\n-      srcmap.sources = [inurl]\n-    return { js, srcmap }\n-\n-  js\n-\n-\n-getUrlPath = (absPath, absStaticRoot, staticRootUrl) ->\n-  absPath = path.resolve path.normalize absPath\n-  absStaticRoot = path.resolve path.normalize absStaticRoot\n-\n-  if absStaticRoot[absStaticRoot.length - 1] isnt '/'\n-    absStaticRoot += '/'\n-\n-  if staticRootUrl[staticRootUrl.length - 1] isnt '/'\n-    staticRootUrl += '/'\n-\n-  absPath.replace absStaticRoot, staticRootUrl\n-\n-\n-sourceMapCat = (opts) ->\n-  generated = new SourceMap.SourceMapGenerator({\n-    # The filename of the generated source (output) that this source\n-    # map is associated with.\n-    file: opts.filename\n-  })\n-\n-  # Last line of the concatenated script so far\n-  combinedGeneratedLine = 1\n-\n-  for _original in opts.maps\n-    if _original.empty? and _original.empty is true\n-      combinedGeneratedLine += _original.numLines\n-      continue\n-\n-    original = new SourceMap.SourceMapConsumer _original\n-    # Last line of the current map source when eachMapping finishes\n-    originalLastLine = null\n-\n-    original.eachMapping (mapping) ->\n-      try\n-        generated.addMapping(\n-          generated:\n-            line: combinedGeneratedLine + mapping.generatedLine\n-            column: mapping.generatedColumn\n-          original:\n-            line: mapping.originalLine\n-            column: mapping.originalColumn\n-          source: mapping.source  # Original source file\n-        )\n-      catch e\n-        throw new Error \"Invalid Mapping: #{JSON.stringify mapping}\"\n+            if fileChanged then graphChanged = true\n+            _content = @cache[filePath].data.toString 'utf8'\n+            for directive in parseDirectives _content\n+                words = directive.replace(/['\"]/g, '').split /\\s+/\n+                [command, relPaths...] = words\n+\n+                switch command\n+                    when 'require'\n+                        require relPath for relPath in relPaths\n+                    when 'require_tree'\n+                        for relPath in relPaths\n+                            requireTree @joinPath path.dirname(filePath),\n+                                relPath\n+\n+            q.finalize()\n+\n+    # Searches for a file with the given name (no extension, e.g. `'foo/bar'`)\n+    findMatchingFile: (filename, flags, callback) ->\n+        tryFiles = (filePaths) =>\n+            for filePath in filePaths\n+                if stripExt(@absPath filePath) is @absPath(filename)\n+                    callback null, filePath\n+                    return true\n+\n+        return if tryFiles _.keys @cache\n+        @readdir path.dirname(@absPath filename), flags, (err, files) =>\n+            return callback err if err\n+            return if tryFiles (for file in files\n+                @joinPath path.dirname(filename), file\n+            )\n+            callback new Error(\"File not found: '#{filename}'\")\n+\n+    # Wrapper around fs.readdir or fs.readdirSync, depending on flags.async.\n+    readdir: (dir, flags, callback) ->\n+        if flags.async\n+            fs.readdir @absPath(dir), callback\n+        else\n+            try\n+                files = fs.readdirSync @absPath(dir)\n+                callback null, files\n+            catch e\n+                callback e\n+\n+    # Wrapper around fs.stat or fs.statSync, depending on flags.async.\n+    stat: (filePath, flags, callback) ->\n+        if flags.async\n+            fs.stat @absPath(filePath), callback\n+        else\n+            try\n+                stats = fs.statSync @absPath(filePath)\n+                callback null, stats\n+            catch e\n+                callback e\n+\n+    # Reads a file's data and timestamp into the cache.\n+    readFile: (filePath, flags, callback) ->\n+        @stat filePath, flags, (err, stats) =>\n+            return callback err if err\n+            if timeEq @cache[filePath]?.mtime, stats.mtime\n+                return callback null, false\n+            if flags.async\n+                fs.readFile @absPath(filePath), (err, data) =>\n+                    return callback err if err\n+                    @cache[filePath] = {mtime: stats.mtime, data}\n+                    callback null, true\n+            else\n+                try\n+                    data = fs.readFileSync @absPath(filePath)\n+                    @cache[filePath] = {mtime: stats.mtime, data}\n+                    callback null, true\n+                catch e\n+                    callback e\n+\n+    compileFile: (filePath) ->\n+        if (ext = path.extname filePath) is '.js'\n+            @cache[filePath].js = @cache[filePath].data\n+            return false\n+        else\n+            src = @cache[filePath].data.toString 'utf8'\n+            pth = @absPath(filePath)\n+            js = compilers[ext[1..]].compileSync @absPath(filePath), src,\n+                @options\n+            unless _.isString js\n+                @cache[filePath].srcmap = js.srcmap\n+                js = js.js\n+            @cache[filePath].js = new Buffer(js)\n+            return true\n+\n+    absPath: (relPath) ->\n+        if relPath.match EXPLICIT_PATH\n+            relPath\n+        else if @options.src.match EXPLICIT_PATH\n+            @joinPath @options.src, relPath","path":"src/snockets.coffee","position":1162,"original_position":1162,"commit_id":"2aea04422ac50a5da3f0ced2465990e4d52f2fb0","original_commit_id":"2aea04422ac50a5da3f0ced2465990e4d52f2fb0","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"Line contains inconsistent indentation","created_at":"2016-08-29T13:48:35Z","updated_at":"2016-08-29T13:48:35Z","html_url":"https://github.com/saimonmoore/snockets/pull/1#discussion_r76609479","pull_request_url":"https://api.github.com/repos/saimonmoore/snockets/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/comments/76609479"},"html":{"href":"https://github.com/saimonmoore/snockets/pull/1#discussion_r76609479"},"pull_request":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/saimonmoore/snockets/pulls/1","id":83101816,"html_url":"https://github.com/saimonmoore/snockets/pull/1","diff_url":"https://github.com/saimonmoore/snockets/pull/1.diff","patch_url":"https://github.com/saimonmoore/snockets/pull/1.patch","issue_url":"https://api.github.com/repos/saimonmoore/snockets/issues/1","number":1,"state":"open","locked":false,"title":"2.0.0 wip","user":{"login":"saimonmoore","id":494,"avatar_url":"https://avatars.githubusercontent.com/u/494?v=3","gravatar_id":"","url":"https://api.github.com/users/saimonmoore","html_url":"https://github.com/saimonmoore","followers_url":"https://api.github.com/users/saimonmoore/followers","following_url":"https://api.github.com/users/saimonmoore/following{/other_user}","gists_url":"https://api.github.com/users/saimonmoore/gists{/gist_id}","starred_url":"https://api.github.com/users/saimonmoore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saimonmoore/subscriptions","organizations_url":"https://api.github.com/users/saimonmoore/orgs","repos_url":"https://api.github.com/users/saimonmoore/repos","events_url":"https://api.github.com/users/saimonmoore/events{/privacy}","received_events_url":"https://api.github.com/users/saimonmoore/received_events","type":"User","site_admin":false},"body":"bla bla test","created_at":"2016-08-29T13:48:19Z","updated_at":"2016-08-29T13:48:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d2f4a93e33120b54b09019f464f7499f6213db43","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/saimonmoore/snockets/pulls/1/commits","review_comments_url":"https://api.github.com/repos/saimonmoore/snockets/pulls/1/comments","review_comment_url":"https://api.github.com/repos/saimonmoore/snockets/pulls/comments{/number}","comments_url":"https://api.github.com/repos/saimonmoore/snockets/issues/1/comments","statuses_url":"https://api.github.com/repos/saimonmoore/snockets/statuses/2aea04422ac50a5da3f0ced2465990e4d52f2fb0","head":{"label":"saimonmoore:2.0.0-wip","ref":"2.0.0-wip","sha":"2aea04422ac50a5da3f0ced2465990e4d52f2fb0","user":{"login":"saimonmoore","id":494,"avatar_url":"https://avatars.githubusercontent.com/u/494?v=3","gravatar_id":"","url":"https://api.github.com/users/saimonmoore","html_url":"https://github.com/saimonmoore","followers_url":"https://api.github.com/users/saimonmoore/followers","following_url":"https://api.github.com/users/saimonmoore/following{/other_user}","gists_url":"https://api.github.com/users/saimonmoore/gists{/gist_id}","starred_url":"https://api.github.com/users/saimonmoore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saimonmoore/subscriptions","organizations_url":"https://api.github.com/users/saimonmoore/orgs","repos_url":"https://api.github.com/users/saimonmoore/repos","events_url":"https://api.github.com/users/saimonmoore/events{/privacy}","received_events_url":"https://api.github.com/users/saimonmoore/received_events","type":"User","site_admin":false},"repo":{"id":16944603,"name":"snockets","full_name":"saimonmoore/snockets","owner":{"login":"saimonmoore","id":494,"avatar_url":"https://avatars.githubusercontent.com/u/494?v=3","gravatar_id":"","url":"https://api.github.com/users/saimonmoore","html_url":"https://github.com/saimonmoore","followers_url":"https://api.github.com/users/saimonmoore/followers","following_url":"https://api.github.com/users/saimonmoore/following{/other_user}","gists_url":"https://api.github.com/users/saimonmoore/gists{/gist_id}","starred_url":"https://api.github.com/users/saimonmoore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saimonmoore/subscriptions","organizations_url":"https://api.github.com/users/saimonmoore/orgs","repos_url":"https://api.github.com/users/saimonmoore/repos","events_url":"https://api.github.com/users/saimonmoore/events{/privacy}","received_events_url":"https://api.github.com/users/saimonmoore/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/saimonmoore/snockets","description":"Sprockets-style script concatenation for Node","fork":true,"url":"https://api.github.com/repos/saimonmoore/snockets","forks_url":"https://api.github.com/repos/saimonmoore/snockets/forks","keys_url":"https://api.github.com/repos/saimonmoore/snockets/keys{/key_id}","collaborators_url":"https://api.github.com/repos/saimonmoore/snockets/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/saimonmoore/snockets/teams","hooks_url":"https://api.github.com/repos/saimonmoore/snockets/hooks","issue_events_url":"https://api.github.com/repos/saimonmoore/snockets/issues/events{/number}","events_url":"https://api.github.com/repos/saimonmoore/snockets/events","assignees_url":"https://api.github.com/repos/saimonmoore/snockets/assignees{/user}","branches_url":"https://api.github.com/repos/saimonmoore/snockets/branches{/branch}","tags_url":"https://api.github.com/repos/saimonmoore/snockets/tags","blobs_url":"https://api.github.com/repos/saimonmoore/snockets/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/saimonmoore/snockets/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/saimonmoore/snockets/git/refs{/sha}","trees_url":"https://api.github.com/repos/saimonmoore/snockets/git/trees{/sha}","statuses_url":"https://api.github.com/repos/saimonmoore/snockets/statuses/{sha}","languages_url":"https://api.github.com/repos/saimonmoore/snockets/languages","stargazers_url":"https://api.github.com/repos/saimonmoore/snockets/stargazers","contributors_url":"https://api.github.com/repos/saimonmoore/snockets/contributors","subscribers_url":"https://api.github.com/repos/saimonmoore/snockets/subscribers","subscription_url":"https://api.github.com/repos/saimonmoore/snockets/subscription","commits_url":"https://api.github.com/repos/saimonmoore/snockets/commits{/sha}","git_commits_url":"https://api.github.com/repos/saimonmoore/snockets/git/commits{/sha}","comments_url":"https://api.github.com/repos/saimonmoore/snockets/comments{/number}","issue_comment_url":"https://api.github.com/repos/saimonmoore/snockets/issues/comments{/number}","contents_url":"https://api.github.com/repos/saimonmoore/snockets/contents/{+path}","compare_url":"https://api.github.com/repos/saimonmoore/snockets/compare/{base}...{head}","merges_url":"https://api.github.com/repos/saimonmoore/snockets/merges","archive_url":"https://api.github.com/repos/saimonmoore/snockets/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/saimonmoore/snockets/downloads","issues_url":"https://api.github.com/repos/saimonmoore/snockets/issues{/number}","pulls_url":"https://api.github.com/repos/saimonmoore/snockets/pulls{/number}","milestones_url":"https://api.github.com/repos/saimonmoore/snockets/milestones{/number}","notifications_url":"https://api.github.com/repos/saimonmoore/snockets/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/saimonmoore/snockets/labels{/name}","releases_url":"https://api.github.com/repos/saimonmoore/snockets/releases{/id}","deployments_url":"https://api.github.com/repos/saimonmoore/snockets/deployments","created_at":"2014-02-18T10:06:39Z","updated_at":"2014-02-18T10:06:40Z","pushed_at":"2016-08-29T13:48:19Z","git_url":"git://github.com/saimonmoore/snockets.git","ssh_url":"git@github.com:saimonmoore/snockets.git","clone_url":"https://github.com/saimonmoore/snockets.git","svn_url":"https://github.com/saimonmoore/snockets","homepage":"","size":1481,"stargazers_count":0,"watchers_count":0,"language":"CoffeeScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"develop"}},"base":{"label":"saimonmoore:master","ref":"master","sha":"1a23c26523c367fda96a5289d93cb1b902af8cc0","user":{"login":"saimonmoore","id":494,"avatar_url":"https://avatars.githubusercontent.com/u/494?v=3","gravatar_id":"","url":"https://api.github.com/users/saimonmoore","html_url":"https://github.com/saimonmoore","followers_url":"https://api.github.com/users/saimonmoore/followers","following_url":"https://api.github.com/users/saimonmoore/following{/other_user}","gists_url":"https://api.github.com/users/saimonmoore/gists{/gist_id}","starred_url":"https://api.github.com/users/saimonmoore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saimonmoore/subscriptions","organizations_url":"https://api.github.com/users/saimonmoore/orgs","repos_url":"https://api.github.com/users/saimonmoore/repos","events_url":"https://api.github.com/users/saimonmoore/events{/privacy}","received_events_url":"https://api.github.com/users/saimonmoore/received_events","type":"User","site_admin":false},"repo":{"id":16944603,"name":"snockets","full_name":"saimonmoore/snockets","owner":{"login":"saimonmoore","id":494,"avatar_url":"https://avatars.githubusercontent.com/u/494?v=3","gravatar_id":"","url":"https://api.github.com/users/saimonmoore","html_url":"https://github.com/saimonmoore","followers_url":"https://api.github.com/users/saimonmoore/followers","following_url":"https://api.github.com/users/saimonmoore/following{/other_user}","gists_url":"https://api.github.com/users/saimonmoore/gists{/gist_id}","starred_url":"https://api.github.com/users/saimonmoore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saimonmoore/subscriptions","organizations_url":"https://api.github.com/users/saimonmoore/orgs","repos_url":"https://api.github.com/users/saimonmoore/repos","events_url":"https://api.github.com/users/saimonmoore/events{/privacy}","received_events_url":"https://api.github.com/users/saimonmoore/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/saimonmoore/snockets","description":"Sprockets-style script concatenation for Node","fork":true,"url":"https://api.github.com/repos/saimonmoore/snockets","forks_url":"https://api.github.com/repos/saimonmoore/snockets/forks","keys_url":"https://api.github.com/repos/saimonmoore/snockets/keys{/key_id}","collaborators_url":"https://api.github.com/repos/saimonmoore/snockets/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/saimonmoore/snockets/teams","hooks_url":"https://api.github.com/repos/saimonmoore/snockets/hooks","issue_events_url":"https://api.github.com/repos/saimonmoore/snockets/issues/events{/number}","events_url":"https://api.github.com/repos/saimonmoore/snockets/events","assignees_url":"https://api.github.com/repos/saimonmoore/snockets/assignees{/user}","branches_url":"https://api.github.com/repos/saimonmoore/snockets/branches{/branch}","tags_url":"https://api.github.com/repos/saimonmoore/snockets/tags","blobs_url":"https://api.github.com/repos/saimonmoore/snockets/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/saimonmoore/snockets/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/saimonmoore/snockets/git/refs{/sha}","trees_url":"https://api.github.com/repos/saimonmoore/snockets/git/trees{/sha}","statuses_url":"https://api.github.com/repos/saimonmoore/snockets/statuses/{sha}","languages_url":"https://api.github.com/repos/saimonmoore/snockets/languages","stargazers_url":"https://api.github.com/repos/saimonmoore/snockets/stargazers","contributors_url":"https://api.github.com/repos/saimonmoore/snockets/contributors","subscribers_url":"https://api.github.com/repos/saimonmoore/snockets/subscribers","subscription_url":"https://api.github.com/repos/saimonmoore/snockets/subscription","commits_url":"https://api.github.com/repos/saimonmoore/snockets/commits{/sha}","git_commits_url":"https://api.github.com/repos/saimonmoore/snockets/git/commits{/sha}","comments_url":"https://api.github.com/repos/saimonmoore/snockets/comments{/number}","issue_comment_url":"https://api.github.com/repos/saimonmoore/snockets/issues/comments{/number}","contents_url":"https://api.github.com/repos/saimonmoore/snockets/contents/{+path}","compare_url":"https://api.github.com/repos/saimonmoore/snockets/compare/{base}...{head}","merges_url":"https://api.github.com/repos/saimonmoore/snockets/merges","archive_url":"https://api.github.com/repos/saimonmoore/snockets/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/saimonmoore/snockets/downloads","issues_url":"https://api.github.com/repos/saimonmoore/snockets/issues{/number}","pulls_url":"https://api.github.com/repos/saimonmoore/snockets/pulls{/number}","milestones_url":"https://api.github.com/repos/saimonmoore/snockets/milestones{/number}","notifications_url":"https://api.github.com/repos/saimonmoore/snockets/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/saimonmoore/snockets/labels{/name}","releases_url":"https://api.github.com/repos/saimonmoore/snockets/releases{/id}","deployments_url":"https://api.github.com/repos/saimonmoore/snockets/deployments","created_at":"2014-02-18T10:06:39Z","updated_at":"2014-02-18T10:06:40Z","pushed_at":"2016-08-29T13:48:19Z","git_url":"git://github.com/saimonmoore/snockets.git","ssh_url":"git@github.com:saimonmoore/snockets.git","clone_url":"https://github.com/saimonmoore/snockets.git","svn_url":"https://github.com/saimonmoore/snockets","homepage":"","size":1481,"stargazers_count":0,"watchers_count":0,"language":"CoffeeScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/1"},"html":{"href":"https://github.com/saimonmoore/snockets/pull/1"},"issue":{"href":"https://api.github.com/repos/saimonmoore/snockets/issues/1"},"comments":{"href":"https://api.github.com/repos/saimonmoore/snockets/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/saimonmoore/snockets/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/saimonmoore/snockets/statuses/2aea04422ac50a5da3f0ced2465990e4d52f2fb0"}}}}
{"actor":{"display_login":"houndci-bot"}}