public bool Run(out string ErrorMessage) { Log.WriteLine("Finding files in workspace..."); Log.WriteLine(); // Query the have table PerforceHaveFolder HaveFolder = new PerforceHaveFolder(); foreach (string SyncPath in SyncPaths) { List <PerforceFileRecord> FileRecords; if (!PerforceClient.Have(SyncPath, out FileRecords, Log)) { ErrorMessage = "Couldn't query have table from Perforce."; return(false); } foreach (PerforceFileRecord FileRecord in FileRecords) { if (!FileRecord.ClientPath.StartsWith(ClientRootPath, StringComparison.InvariantCultureIgnoreCase)) { ErrorMessage = String.Format("Failed to get have table; file '{0}' doesn't start with client root path ('{1}')", FileRecord.ClientPath, ClientRootPath); return(false); } string[] Tokens = FileRecord.ClientPath.Substring(ClientRootPath.Length).Split('/', '\\'); PerforceHaveFolder FileFolder = HaveFolder; for (int Idx = 0; Idx < Tokens.Length - 1; Idx++) { PerforceHaveFolder NextFileFolder; if (!FileFolder.SubFolders.TryGetValue(Tokens[Idx], out NextFileFolder)) { NextFileFolder = new PerforceHaveFolder(); FileFolder.SubFolders.Add(Tokens[Idx], NextFileFolder); } FileFolder = NextFileFolder; } FileFolder.Files.Add(Tokens[Tokens.Length - 1]); } } // Wait to finish scanning the directory FinishedScan.WaitOne(); // Remove all the files in the have table from the list of files to delete RemoveFilesToKeep(RootFolderToClean, HaveFolder); // Remove all the empty folders RemoveEmptyFolders(RootFolderToClean); ErrorMessage = null; return(true); }