fix(audit-license-headers): RAT tool download on Windows (#256)

* fix(audit-license-headers): RAT tool download on Windows

Downloads and extracts Apache RAT using Node.js libraries instead of
unix-specific CLI utilities.

Fixes #240

* test(audit-license-headers): add basic smoke test
diff --git a/package.json b/package.json
index b997ad2..4bcc036 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "co": "~4.0",
     "co-stream": "0.1.1",
     "glob": "^5.0.14",
+    "got": "^9.6.0",
     "inquirer": "2.0.0",
     "jira-client": "4.2.0",
     "jira-linkify": "^2.3.0",
@@ -21,6 +22,7 @@
     "request": "^2.88.0",
     "semver": "^4.2.0",
     "shelljs": "0.1.4",
+    "tar-fs": "^2.0.0",
     "treeify": "^1.0.1",
     "xml2js": "0.4.17"
   },
diff --git a/spec/audit-license-headers.spec.js b/spec/audit-license-headers.spec.js
new file mode 100644
index 0000000..8963e81
--- /dev/null
+++ b/spec/audit-license-headers.spec.js
@@ -0,0 +1,36 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you 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.
+*/
+
+require('jasmine-co').install();
+const path = require('path');
+const shell = require('shelljs');
+const repoutil = require('../src/repoutil');
+const auditLicenseHeaders = require('../src/audit-license-headers');
+
+describe('audit-license-headers', () => {
+    describe('scrubRepos', () => {
+        it('basic operation', function * () {
+            spyOn(console, 'log');
+            shell.rm('-rf', path.join(__dirname, '../apache-rat-*'));
+
+            const cohoRepo = repoutil.getRepoById('coho');
+            yield auditLicenseHeaders.scrubRepos([cohoRepo], true);
+        });
+    });
+});
diff --git a/src/audit-license-headers.js b/src/audit-license-headers.js
index 4d2e7f7..e2ac2a2 100644
--- a/src/audit-license-headers.js
+++ b/src/audit-license-headers.js
@@ -20,12 +20,15 @@
 var fs = require('fs');
 var path = require('path');
 var chalk = require('chalk');
-var shelljs = require('shelljs');
 var optimist = require('optimist');
-var apputil = require('./apputil');
 var executil = require('./executil');
 var flagutil = require('./flagutil');
 var repoutil = require('./repoutil');
+const { promisify } = require('util');
+const pipeline = promisify(require('stream').pipeline);
+const zlib = require('zlib');
+const got = require('got');
+const tar = require('tar-fs');
 
 // constants
 var COMMON_RAT_EXCLUDES = [
@@ -93,16 +96,15 @@
     if (!fs.existsSync(ratPath)) {
         console.log('RAT tool not found, downloading to: ' + ratPath);
         yield repoutil.forEachRepo([repoutil.getRepoById('coho')], function * () {
-            // TODO: this will not work on windows right?
-            if (shelljs.which('curl')) {
-                yield executil.execHelper(['sh', '-c', 'curl "' + RAT_URL + '" | tar xz']);
-            } else {
-                yield executil.execHelper(['sh', '-c', 'wget -O - "' + RAT_URL + '" | tar xz']);
-            }
+            yield pipeline(
+                got.stream(RAT_URL),
+                zlib.createGunzip(),
+                tar.extract('.')
+            ).catch(error => {
+                error.message = 'Failed to get RAT binary:\n' + error.message;
+                throw error;
+            });
         });
-        if (!fs.existsSync(ratPath)) {
-            apputil.fatal('Download failed.');
-        }
     }
 
     console.log(chalk.red('Note: ignore filters reside in a repo\'s .ratignore and in COMMON_RAT_EXCLUDES in audit-license-headers.js.'));