blob: ca779bb9fb503bb150217511cf5365c5a2e6ccbd [file] [log] [blame]
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// References:
//
// JScript Language Reference
// http://msdn2.microsoft.com/en-us/library/yek4tbz0
//
// Windows Script Host Object Model
// http://msdn2.microsoft.com/en-us/library/a74hyyw0
//
// Script Runtime
// http://msdn2.microsoft.com/en-us/library/hww8txat.aspx
//
function ArrayAny(arr, callback) {
/// <summary>Checks whether any element in an array satisfies a predicate.</summary>
/// <param name="arr" type="Array">Array to operate on.</param>
/// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param>
/// <returns type="Boolean">true if 'callback' returns true for any element; false otherwise.</returns>
for (var i = 0; i < arr.length; i++) {
if (callback(arr[i], i)) {
return true;
}
}
return false;
}
function ArrayWhere(arr, callback) {
/// <summary>Returns the elements in an array that satisfy a predicate.</summary>
/// <param name="arr" type="Array">Array to operate on.</param>
/// <param name="callback" type="Function">Function to test with element and index, returning true or false.</param>
/// <returns type="Array">Array of elements from arr that satisfy the predicate.</returns>
var result = [];
for (var i = 0; i < arr.length; i++) {
if (callback(arr[i], i)) {
result.push(arr[i]);
}
}
return result;
}
function ArrayForEach(arr, callback) {
/// <summary>Invokes a callback for each element in the array.</summary>
/// <param name="arr" type="Array">Array to operate on.</param>
/// <param name="callback" type="Function">Function to invoke with element and index.</param>
for (var i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}
function CheckScriptFlag(name) {
/// <summary>Checks whether a script argument was given with true or false.</summary>
/// <param name="name" type="String">Argument name to check.</param>
/// <returns type="Boolean">
/// true if the argument was given witha value of 'true' or 'True'; false otherwise.
/// </returns>
var flag = WScript.Arguments.Named(name);
if (!flag) {
return false;
}
return flag === "true" || flag === "True";
}
function CreateFolderIfMissing(path) {
/// <summary>Creates a folder if it doesn't exist.</summary>
/// <param name="path" type="String">Path to folder to create.</param>
/// <remarks>This function will write out to the console on creation.</remarks>
if (!path) return;
var parent = PathGetDirectory(path);
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (!fso.FolderExists(parent)) {
CreateFolderIfMissing(parent);
}
if (!fso.FolderExists(path)) {
WScript.Echo("Creating " + path + "...");
fso.CreateFolder(path);
}
}
function DeleteFile(path, force) {
/// <summary>Deletes a file.</summary>
/// <param name="path" type="String">Path to the file.</param>
/// <param name="force" type="Boolean">Whether to delete the file even if it has the read-only attribute set.</param>
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFile(path, force);
}
function DeleteFolder(path, force) {
/// <summary>Deletes a folder.</summary>
/// <param name="path" type="String">Path to the folder.</param>
/// <param name="force" type="Boolean">Whether to delete the folder even if it has the read-only attribute set.</param>
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFolder(path, force);
}
function CopyFolder(source, dest, overwrite) {
/// <summary>Recursively copies a folder and its contents from source to dest.</summary>
/// <param name="source" type="String">Path to the source folder location.</param>
/// <param name="dest" type="String">Path to the destination folder location.</param>
/// <param name="overwrite" type="Boolean">Whether to overwrite a folder in the destination location.</param>
var fso = new ActiveXObject("Scripting.FileSystemObject");
fso.CopyFolder(source, dest, overwrite);
}
function CopyFile(source, dest, overwrite) {
/// <summary>Copies a file from source to dest.</summary>
/// <param name="source" type="String">Path to the source file location.</param>
/// <param name="dest" type="String">Path to the destination file location.</param>
/// <param name="overwrite" type="Boolean">Whether to overwrite a file in the destination location.</param>
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (overwrite && fso.FileExists(dest)) {
var f = fso.getFile(dest);
f.attributes = 0;
}
fso.CopyFile(source, dest, overwrite);
}
function ExtractContentsBetweenMarkers(path, contentOnly, isExclusion, startMarker, endMarker, callback) {
/// <summary>
/// Extracts the lines from the 'path' text file between the start and end markers.
/// </summary>
/// <param name="path" type="String">Path to file.</param>
/// <param name="contentOnly" type="Boolean">
/// true to skip everything until it's found between markers, false to start including everything from the start.
/// </param>
/// <param name="isExclusion" type="Boolean">
/// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
/// </param>
/// <param name="startMarker" type="String">Line content to match for content start.</param>
/// <param name="endMarker" type="String">Line content to match for content end.</param>
/// <param name="callback" type="Function" mayBeNull="true">
/// If true, then this function is called for every line along with the inContent flag
/// before the line is added; the called function may return a line
/// to be added in its place, null to skip processing.
/// </param>
/// <returns type="String">The string content of the file.</returns>
var content = ReadAllTextFile(path);
return ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback);
}
function ExtractContentsBetweenMarkersForText(content, contentOnly, isExclusion, startMarker, endMarker, callback) {
/// <summary>
/// Extracts the lines from the specified text between the start and end markers.
/// </summary>
/// <param name="content" type="String">Text to process.</param>
/// <param name="contentOnly" type="Boolean">
/// true to skip everything until it's found between markers, false to start including everything from the start.
/// </param>
/// <param name="isExclusion" type="Boolean">
/// false if the 'extraction' means keeping the content; true if it means not excluding it from the result.
/// </param>
/// <param name="startMarker" type="String">Line content to match for content start.</param>
/// <param name="endMarker" type="String">Line content to match for content end.</param>
/// <param name="callback" type="Function" mayBeNull="true">
/// If true, then this function is called for every line along with the inContent flag
/// before the line is added; the called function may return a line
/// to be added in its place, null to skip processing.
/// </param>
/// <returns type="String">The extracted content.</returns>
var inContent = contentOnly === false;
var lines = StringSplit(content, "\r\n");
var result = [];
var i, len;
for (i = 0, len = lines.length; i < len; i++) {
var line = lines[i];
var contentStartIndex = line.indexOf(startMarker);
if (inContent === false && contentStartIndex !== -1) {
inContent = true;
continue;
}
var contentEndIndex = line.indexOf(endMarker);
if (inContent === true && contentEndIndex !== -1) {
inContent = false;
continue;
}
if (inContent !== isExclusion) {
if (callback) {
var callbackResult = callback(line, inContent);
if (callbackResult !== null && callbackResult !== undefined) {
result.push(callbackResult);
}
} else {
result.push(line);
}
}
}
return result.join("\r\n");
}
function FolderExists(path) {
/// <summary>Checks whether the specified directory exists.</summary>
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FolderExists(path)) {
return true;
}
else {
return false;
}
}
function FileExists(path) {
/// <summary>Checks whether the specified file exists.</summary>
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FileExists(path)) {
return true;
}
else {
return false;
}
}
function GetEnvironmentVariable(name) {
/// <summary>Gets the value of the specified environment variable.</summary>
/// <param name="name" type="String">Name of the variable value to get.</param>
/// <returns type="String">Value for the given environment variable; null if undefined.</returns>
var shell = new ActiveXObject("WScript.Shell");
var result = shell.ExpandEnvironmentStrings("%" + name + "%");
if (result == "%" + name + "%") {
result = null;
}
return result;
}
function GetFilesRecursive(path) {
/// <summary>Gets all file names under the specified directory path.</summary>
/// <param name="path" type="String">Path to directory.</param>
/// <returns type="Array">Array of all file names under path.</returns>
var result = [];
var fso = new ActiveXObject("Scripting.FileSystemObject");
var pending = [path];
while (pending.length) {
var item = pending.pop();
var folder = fso.GetFolder(item);
for (var files = new Enumerator(folder.Files); !files.atEnd(); files.moveNext()) {
result.push(files.item().Path);
}
for (var subFolders = new Enumerator(folder.SubFolders); !subFolders.atEnd(); subFolders.moveNext()) {
pending.push(subFolders.item().Path);
}
}
return result;
}
function GetRelativePathFrom(startPath, endPath) {
if (startPath[startPath.length - 1] !== "\\") {
startPath += "\\";
}
if (startPath.length > endPath.length) {
throw { message: "traversing up NYI" };
}
return endPath.substr(startPath.length);
}
function MatchesMask(file, mask) {
if (!mask) {
return false;
}
if (file === mask) {
return true;
}
if (mask.substr(0, 1) === "*") {
var rest = mask.substr(1);
return file.substr(file.length - rest.length) === rest;
} else if (mask.substr(mask.length - 1) === "*") {
var end = mask.substr(0, mask.length - 1);
return file.substr(0, end.length) === end;
}
return false;
}
function PathGetDirectory(path) {
/// <summary>
/// Returns the directory of the specified path string (excluding the trailing "\\");
/// empty if there is no path.
/// </summary>
var l = path.length;
var startIndex = l;
while (--startIndex >= 0) {
var ch = path.substr(startIndex, 1);
if (ch == "\\") {
if (startIndex === 0) {
return "";
} else {
return path.substr(0, startIndex);
}
}
}
return "";
}
function PathGetFileName(path) {
/// <summary>
/// Returns the file name for the specified path string; empty if there is no
/// directory information.
/// </summary>
var l = path.length;
var startIndex = l;
while (--startIndex >= 0) {
var ch = path.substr(startIndex, 1);
if (ch == "\\" || ch == "/" || ch == ":") {
return path.substr(startIndex, l - startIndex);
}
}
return "";
}
function PathGetExtension(path) {
/// <summary>
/// Returns the extension of the specified path string (including the ".");
/// empty if there is no extension.
/// </summary>
var l = path.length;
var startIndex = l;
while (--startIndex >= 0) {
var ch = path.substr(startIndex, 1);
if (ch == ".") {
if (startIndex != (l - 1)) {
return path.substr(startIndex, l - startIndex);
}
return "";
}
else if (ch == "\\" || ch == ":") {
break;
}
}
return "";
}
function ReadAllTextFile(path) {
/// <summary>Reads all the content of the file into a string.</summary>
/// <param name="path" type="String">File name to read from.</param>
/// <returns type="String">File contents.</returns>
var ForReading = 1, ForWriting = 2;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile(path, ForReading);
try {
var result;
if (file.AtEndOfStream) {
result = "";
} else {
result = file.ReadAll();
}
} finally {
file.Close();
}
return result;
}
function ReadXmlFile(path) {
/// <summary>Reads an XML document from the specified path.</summary>
/// <param name="path" type="String">Path to file on disk.</param>
/// <returns>A DOMDocument with the contents of the given file.</returns>
var result = new ActiveXObject("Msxml2.DOMDocument.6.0");
result.async = false;
result.load(path);
if (result.parseError.errorCode !== 0) {
throw { message: "Error reading '" + path + "': " + result.parseError.reason };
}
return result;
}
// Runs the specified function catching exceptions and quits the current script.
function RunAndQuit(f) {
try {
f();
}
catch (e) {
// An error with 'statusCode' defined will avoid the usual error dump handling.
if (e.statusCode !== undefined) {
if (e.message) {
WScript.Echo(e.message);
}
WScript.Quit(e.statusCode);
}
WScript.Echo("Error caught while running this function:");
WScript.Echo(f.toString());
WScript.Echo("Error details:");
if (typeof (e) == "object" && e.toString() == "[object Object]" || e.toString() === "[object Error]") {
for (var p in e) WScript.Echo(" " + p + ": " + e[p]);
}
else {
WScript.Echo(e);
}
WScript.Quit(1);
}
WScript.Quit(0);
}
function RunConsoleCommand(strCommand, timeout, retry) {
/// <summary>Runs a command and waits for it to exit.</summary>
/// <param name="strCommand" type="String">Command to run.</param>
/// <param name="timeout" type="int">Timeout in seconds.</param>
/// <param name="timeout" type="bool">Boolean specifying whether to retry on timeout or not.</param>
/// <returns type="Array">An array with stdout in 0, stderr in 1 and exit code in 2. Forced
/// termination sets 2 to 1.</returns>
var WshShell = new ActiveXObject("WScript.Shell");
var result = new Array(3);
var oExec = WshShell.Exec(strCommand);
var counter = 0;
if (timeout) {
// Status of 0 means the process is still running
while (oExec.Status === 0 && counter < timeout) {
WScript.Sleep(1000);
counter++;
}
if (timeout === counter && oExec.Status === 0) {
WScript.Echo("Forcefully terminating " + strCommand + " after " + timeout + " seconds.");
oExec.Terminate();
result[2] = 1;
if (retry) {
return RunConsoleCommand(strCommand, timeout, false);
}
}
}
result[0] = oExec.StdOut.ReadAll();
result[1] = oExec.StdErr.ReadAll();
if (!result[2]) {
result[2] = oExec.ExitCode;
}
return result;
}
function SaveTextToFile(content, path) {
/// <summary>Saves text content into a file.</summary>
/// <param name="content" type="String">Content to save.</param>
/// <param name="path" type="String">Path of file to save into.</param>
var ForReading = 1, ForWriting = 2;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.OpenTextFile(path, ForWriting, true);
file.Write(content);
file.Close();
}
function StringSplit(strLine, strSeparator) {
/// <summary>Splits a string into a string array.</summary>
var result = new Array();
var startIndex = 0;
var resultIndex = 0;
while (startIndex < strLine.length) {
var endIndex = strLine.indexOf(strSeparator, startIndex);
if (endIndex == -1) {
endIndex = strLine.length;
}
result[resultIndex] = strLine.substring(startIndex, endIndex);
startIndex = endIndex + strSeparator.length;
resultIndex++;
}
return result;
}
function PathCombine(path1, path2) {
if (path1.charAt(path1.length - 1) !== "\\") {
return path1 + "\\" + path2;
}
return path1 + path2;
}
function RemoveReadOnlyAttribute(path) {
/// <summary>Removes the read-only attribute on the specified file.</summary>
/// <param name="path" type="String">Path to the file.</param>
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.getFile(path);
if (1 === (f.attributes & 1)) {
f.attributes = (f.attributes & ~1);
}
}
function WriteXmlFile(document, path) {
/// <summary>Write an XML document to the specified path.</summary>
/// <param name="path" type="String">Path to file on disk.</param>
document.save(path);
}