public virtual List <IBuild> GetBuildsAtPath(string InProjectName, string InPath, int MaxRecursion = 3) { List <DirectoryInfo> AllDirs = new List <DirectoryInfo>(); List <IBuild> Builds = new List <IBuild>(); // c:\path\to\build DirectoryInfo PathDI = new DirectoryInfo(InPath); if (PathDI.Exists) { // If the path is directly to a platform folder, add us if (PathDI.Name.IndexOf(PlatformFolderPrefix, StringComparison.OrdinalIgnoreCase) >= 0) { AllDirs.Add(PathDI); } // Assume it's a folder of all build types so find all sub directories that begin with the foldername for this platform IEnumerable <DirectoryInfo> MatchingDirs = PathDI.GetDirectories("*", SearchOption.TopDirectoryOnly); MatchingDirs = MatchingDirs.Where(D => D.Name.StartsWith(PlatformFolderPrefix, StringComparison.OrdinalIgnoreCase)).ToArray(); AllDirs.AddRange(MatchingDirs); List <DirectoryInfo> DirsToRecurse = AllDirs; // now get subdirs while (MaxRecursion-- > 0) { List <DirectoryInfo> DiscoveredDirs = new List <DirectoryInfo>(); DirsToRecurse.ToList().ForEach((D) => { DiscoveredDirs.AddRange(D.GetDirectories("*", SearchOption.TopDirectoryOnly)); }); AllDirs.AddRange(DiscoveredDirs); DirsToRecurse = DiscoveredDirs; } // every directory that contains a valid build should have at least a ProjectName folder AllDirs = AllDirs.Where(D => { var SubDirs = D.GetDirectories(); return(SubDirs.Any(SD => SD.Name.Equals(InProjectName, StringComparison.OrdinalIgnoreCase))); }).ToList(); foreach (DirectoryInfo Di in AllDirs) { IEnumerable <IBuild> FoundBuilds = StagedBuild.CreateFromPath <T>(Platform, InProjectName, Di.FullName, ExecutableExtension); if (FoundBuilds != null) { Builds.AddRange(FoundBuilds); } } } return(Builds); }
protected IAppInstall InstallStagedBuild(UnrealAppConfig AppConfig, StagedBuild InBuild) { bool SkipDeploy = Globals.Params.ParseParam("SkipDeploy"); string BuildPath = InBuild.BuildPath; if (CanRunFromPath(BuildPath) == false) { string SubDir = string.IsNullOrEmpty(AppConfig.Sandbox) ? AppConfig.ProjectName : AppConfig.Sandbox; string DestPath = Path.Combine(this.TempDir, SubDir, AppConfig.ProcessType.ToString()); if (!SkipDeploy) { StagedBuild.InstallBuildParallel(AppConfig, InBuild, BuildPath, DestPath, ToString()); } else { Log.Info("Skipping install of {0} (-skipdeploy)", BuildPath); } Utils.SystemHelpers.MarkDirectoryForCleanup(DestPath); BuildPath = DestPath; } WindowsAppInstall WinApp = new WindowsAppInstall(AppConfig.Name, AppConfig.ProjectName, this); WinApp.RunOptions = RunOptions; // Set commandline replace any InstallPath arguments with the path we use WinApp.CommandArguments = Regex.Replace(AppConfig.CommandLine, @"\$\(InstallPath\)", BuildPath, RegexOptions.IgnoreCase); if (string.IsNullOrEmpty(UserDir) == false) { WinApp.CommandArguments += string.Format(" -userdir=\"{0}\"", UserDir); WinApp.ArtifactPath = Path.Combine(UserDir, @"Saved"); Utils.SystemHelpers.MarkDirectoryForCleanup(UserDir); } else { // e.g d:\Unreal\GameName\Saved WinApp.ArtifactPath = Path.Combine(BuildPath, AppConfig.ProjectName, @"Saved"); } // clear artifact path if (Directory.Exists(WinApp.ArtifactPath)) { try { Directory.Delete(WinApp.ArtifactPath, true); } catch (Exception Ex) { Log.Warning("Failed to delete {0}. {1}", WinApp.ArtifactPath, Ex.Message); } } if (LocalDirectoryMappings.Count == 0) { PopulateDirectoryMappings(Path.Combine(BuildPath, AppConfig.ProjectName), UserDir); } if (AppConfig.FilesToCopy != null) { foreach (UnrealFileToCopy FileToCopy in AppConfig.FilesToCopy) { string PathToCopyTo = Path.Combine(LocalDirectoryMappings[FileToCopy.TargetBaseDirectory], FileToCopy.TargetRelativeLocation); if (File.Exists(FileToCopy.SourceFileLocation)) { FileInfo SrcInfo = new FileInfo(FileToCopy.SourceFileLocation); SrcInfo.IsReadOnly = false; string DirectoryToCopyTo = Path.GetDirectoryName(PathToCopyTo); if (!Directory.Exists(DirectoryToCopyTo)) { Directory.CreateDirectory(DirectoryToCopyTo); } if (File.Exists(PathToCopyTo)) { FileInfo ExistingFile = new FileInfo(PathToCopyTo); ExistingFile.IsReadOnly = false; } SrcInfo.CopyTo(PathToCopyTo, true); Log.Info("Copying {0} to {1}", FileToCopy.SourceFileLocation, PathToCopyTo); } else { Log.Warning("File to copy {0} not found", FileToCopy); } } } if (Path.IsPathRooted(InBuild.ExecutablePath)) { WinApp.ExecutablePath = InBuild.ExecutablePath; } else { // TODO - this check should be at a higher level.... string BinaryPath = Path.Combine(BuildPath, InBuild.ExecutablePath); // check for a local newer executable if (Globals.Params.ParseParam("dev") && AppConfig.ProcessType.UsesEditor() == false) { string LocalBinary = Path.Combine(Environment.CurrentDirectory, InBuild.ExecutablePath); bool LocalFileExists = File.Exists(LocalBinary); bool LocalFileNewer = LocalFileExists && File.GetLastWriteTime(LocalBinary) > File.GetLastWriteTime(BinaryPath); Log.Verbose("Checking for newer binary at {0}", LocalBinary); Log.Verbose("LocalFile exists: {0}. Newer: {1}", LocalFileExists, LocalFileNewer); if (LocalFileExists && LocalFileNewer) { // need to -basedir to have our exe load content from the path WinApp.CommandArguments += string.Format(" -basedir={0}", Path.GetDirectoryName(BinaryPath)); BinaryPath = LocalBinary; } } WinApp.ExecutablePath = BinaryPath; } return(WinApp); }
protected IAppInstall InstallStagedBuild(UnrealAppConfig AppConfig, StagedBuild InBuild) { bool SkipDeploy = Globals.Params.ParseParam("SkipDeploy"); string BuildPath = InBuild.BuildPath; // Must be on our volume to run string BuildVolume = GetVolumeName(BuildPath); string LocalRoot = GetVolumeName(Environment.CurrentDirectory); if (BuildVolume.Equals(LocalRoot, StringComparison.OrdinalIgnoreCase) == false) { string SubDir = string.IsNullOrEmpty(AppConfig.Sandbox) ? AppConfig.ProjectName : AppConfig.Sandbox; string DestPath = Path.Combine(this.TempDir, SubDir, AppConfig.ProcessType.ToString()); if (!SkipDeploy) { Log.Info("Installing {0} to {1}", AppConfig.Name, ToString()); Log.Verbose("\tCopying {0} to {1}", BuildPath, DestPath); Gauntlet.Utils.SystemHelpers.CopyDirectory(BuildPath, DestPath, Utils.SystemHelpers.CopyOptions.Mirror); } else { Log.Info("Skipping install of {0} (-skipdeploy)", BuildPath); } Utils.SystemHelpers.MarkDirectoryForCleanup(DestPath); BuildPath = DestPath; } MacAppInstall MacApp = new MacAppInstall(AppConfig.Name, this); MacApp.LocalPath = BuildPath; MacApp.WorkingDirectory = MacApp.LocalPath; MacApp.RunOptions = RunOptions; // Set commandline replace any InstallPath arguments with the path we use MacApp.CommandArguments = Regex.Replace(AppConfig.CommandLine, @"\$\(InstallPath\)", BuildPath, RegexOptions.IgnoreCase); // Mac always forces this to stop logs and other artifacts going to different places // Mac always forces this to stop logs and other artifacts going to different places MacApp.CommandArguments += string.Format(" -userdir={0}", UserDir); MacApp.ArtifactPath = Path.Combine(UserDir, @"Saved"); // temp - Mac doesn't support -userdir? //MacApp.ArtifactPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Logs", AppConfig.ProjectName); // clear artifact path if (Directory.Exists(MacApp.ArtifactPath)) { try { Directory.Delete(MacApp.ArtifactPath, true); } catch (Exception Ex) { Log.Warning("Failed to delete {0}. {1}", MacApp.ArtifactPath, Ex.Message); } } if (Path.IsPathRooted(InBuild.ExecutablePath)) { MacApp.ExecutablePath = InBuild.ExecutablePath; } else { // TODO - this check should be at a higher level.... string BinaryPath = Path.Combine(BuildPath, InBuild.ExecutablePath); // check for a local newer executable if (Globals.Params.ParseParam("dev") && AppConfig.ProcessType.UsesEditor() == false) { string LocalBinary = Path.Combine(Environment.CurrentDirectory, InBuild.ExecutablePath); bool LocalFileExists = File.Exists(LocalBinary); bool LocalFileNewer = LocalFileExists && File.GetLastWriteTime(LocalBinary) > File.GetLastWriteTime(BinaryPath); Log.Verbose("Checking for newer binary at {0}", LocalBinary); Log.Verbose("LocalFile exists: {0}. Newer: {1}", LocalFileExists, LocalFileNewer); if (LocalFileExists && LocalFileNewer) { // need to -basedir to have our exe load content from the path MacApp.CommandArguments += string.Format(" -basedir={0}", Path.GetDirectoryName(BinaryPath)); BinaryPath = LocalBinary; } } MacApp.ExecutablePath = BinaryPath; } // now turn the Foo.app into Foo/Content/MacOS/Foo string AppPath = Path.GetDirectoryName(MacApp.ExecutablePath); string FileName = Path.GetFileNameWithoutExtension(MacApp.ExecutablePath); MacApp.ExecutablePath = Path.Combine(MacApp.ExecutablePath, "Contents", "MacOS", FileName); return(MacApp); }
/// <summary> /// When running parallel tests using staged builds, local desktop devices only need one copy of client/server /// this method is used to coordinate the copy across multiple local devices /// </summary> public static void InstallBuildParallel(UnrealAppConfig AppConfig, StagedBuild InBuild, string BuildPath, string DestPath, string Desc) { // In parallel tests, we only want to copy the client/server once bool Install = false; InstallStatus Status = InstallStatus.Error; lock (Globals.MainLock) { if (!LocalInstalls.ContainsKey(InBuild)) { Install = true; LocalInstalls[InBuild] = Status = InstallStatus.Installing; } else { Status = LocalInstalls[InBuild]; } } // check if we've already errored in another thread if (Status == InstallStatus.Error) { throw new AutomationException("Parallel build error installing {0} to {1}", BuildPath, DestPath); } if (Install) { try { Log.Info("Installing {0} to {1}", AppConfig.Name, Desc); Log.Verbose("\tCopying {0} to {1}", BuildPath, DestPath); Utils.SystemHelpers.CopyDirectory(BuildPath, DestPath, Utils.SystemHelpers.CopyOptions.Mirror); } catch (Exception Ex) { lock (Globals.MainLock) { LocalInstalls[InBuild] = InstallStatus.Error; } throw Ex; } lock (Globals.MainLock) { LocalInstalls[InBuild] = InstallStatus.Installed; } } else { DateTime StartTime = DateTime.Now; while (true) { if ((DateTime.Now - StartTime).TotalMinutes > 60) { throw new AutomationException("Parallel build error installing {0} to {1}, timed out after an hour", BuildPath, DestPath); } Thread.Sleep(1000); lock (Globals.MainLock) { Status = LocalInstalls[InBuild]; } // install process failed in other thread, disk full, etc if (Status == InstallStatus.Error) { throw new AutomationException("Error installing parallel build from {0} to {1}", BuildPath, DestPath); } if (Status == InstallStatus.Installed) { Log.Verbose("Parallel build successfully installed from {0} to {1}", BuildPath, DestPath); break; } } } }