whole_func_string: function(dir) {
        var drivePrefix = "";
        if (process.platform === "win32" && dir.match(/^[a-zA-Z]:/)) {
          drivePrefix = dir.substring(0, 2);
          dir = dir.substring(2);
        }
        dir = dir.replace(/\\/g, "/");
        var segs = dir.split("/");
        if (!segs.length) {
          return drivePrefix + dir;
        }  
        
        var currentDir;
        var index;
        if (segs[0].length) {
          currentDir = "";
          index = 0;
        } else {
          currentDir = "/";
          index = 1;
        }
        
        function bumpToNext(nextSeg) {
          index++;
          if (currentDir.length && currentDir !== "/") {
            currentDir += "/";
          }  
          currentDir += nextSeg;
          return next();
        }
        
        function next() {
          if (index == segs.length) {
            if (process.platform === "win32") {
              currentDir = currentDir.replace(/\//g, "\\"); 
            }
            return Promise.resolve(drivePrefix + currentDir);
          }
          
          let nextSeg = segs[index];
          if (nextSeg == "." || nextSeg == "..") {
            return bumpToNext(nextSeg);
          }
          
          return new Promise((resolve, reject) => {
            fs.readdir(currentDir.length == 0 ? "." : drivePrefix + currentDir, { encoding: "utf8" }, (err, files) => {
              if (err) {
                reject(err);
                return;
              }
              
              let nextLowerCase = nextSeg.toLowerCase();
              let exact = false;
              let insensitive = null;
              for (let i = 0; i < files.length; i++) {
                if (files[i] === nextSeg) {
                  exact = true;
                  break;
                }
                if (files[i].toLowerCase() === nextLowerCase) {
                  insensitive = files[i];
                }
              }
              if (!exact && insensitive) {
                nextSeg = insensitive;
              }
              
              bumpToNext(nextSeg).then(resolve);
            });
          });
        }
        
        return new Promise((resolve, reject) => {
          fs.stat(drivePrefix + dir, err => {
            if (err) {
              if (err.code == "ENOENT") {
                resolve(drivePrefix + dir);
              } else {
                reject(err);
              }
            } else {
              next().then(resolve);
            }
          });
        });
      }
func_code_string: function(dir) {
        var drivePrefix = "";
        if (process.platform === "win32" && dir.match(/^[a-zA-Z]:/)) {
          drivePrefix = dir.substring(0, 2);
          dir = dir.substring(2);
        }
        dir = dir.replace(/\\/g, "/");
        var segs = dir.split("/");
        if (!segs.length) {
          return drivePrefix + dir;
        }  
        
        var currentDir;
        var index;
        if (segs[0].length) {
          currentDir = "";
          index = 0;
        } else {
          currentDir = "/";
          index = 1;
        }
        
        function bumpToNext(nextSeg) {
          index++;
          if (currentDir.length && currentDir !== "/") {
            currentDir += "/";
          }  
          currentDir += nextSeg;
          return next();
        }
        
        function next() {
          if (index == segs.length) {
            if (process.platform === "win32") {
              currentDir = currentDir.replace(/\//g, "\\"); 
            }
            return Promise.resolve(drivePrefix + currentDir);
          }
          
          let nextSeg = segs[index];
          if (nextSeg == "." || nextSeg == "..") {
            return bumpToNext(nextSeg);
          }
          
          return new Promise((resolve, reject) => {
            fs.readdir(currentDir.length == 0 ? "." : drivePrefix + currentDir, { encoding: "utf8" }, (err, files) => {
              if (err) {
                reject(err);
                return;
              }
              
              let nextLowerCase = nextSeg.toLowerCase();
              let exact = false;
              let insensitive = null;
              for (let i = 0; i < files.length; i++) {
                if (files[i] === nextSeg) {
                  exact = true;
                  break;
                }
                if (files[i].toLowerCase() === nextLowerCase) {
                  insensitive = files[i];
                }
              }
              if (!exact && insensitive) {
                nextSeg = insensitive;
              }
              
              bumpToNext(nextSeg).then(resolve);
            });
          });
        }
        
        return new Promise((resolve, reject) => {
          fs.stat(drivePrefix + dir, err => {
            if (err) {
              if (err.code == "ENOENT") {
                resolve(drivePrefix + dir);
              } else {
                reject(err);
              }
            } else {
              next().then(resolve);
            }
          });
        });
      }
func_documentation_string: Normalises the path and corrects the case of the path to match what is actually on the filing system
  
  @param fsPath {String} the filename to normalise
  @returns {String} the new path
  @async