public static IEnumerable <IOSBuild> CreateFromPath(string InProjectName, string InPath) { string BuildPath = InPath; List <IOSBuild> DiscoveredBuilds = new List <IOSBuild>(); DirectoryInfo Di = new DirectoryInfo(BuildPath); // find all install batchfiles FileInfo[] InstallFiles = Di.GetFiles("*.ipa"); foreach (FileInfo Fi in InstallFiles) { var UnrealConfig = UnrealHelpers.GetConfigurationFromExecutableName(InProjectName, Fi.Name); Log.Verbose("Pulling package data from {0}", Fi.FullName); string AbsPath = Fi.Directory.FullName; // IOS builds are always packaged, and can always replace the command line and executable as we cache the unzip'd IPA BuildFlags Flags = BuildFlags.Packaged | BuildFlags.CanReplaceCommandLine | BuildFlags.CanReplaceExecutable; if (AbsPath.Contains("Bulk")) { Flags |= BuildFlags.Bulk; } else { Flags |= BuildFlags.NotBulk; } string SourceIPAPath = Fi.FullName; string PackageName = GetBundleIdentifier(SourceIPAPath); if (String.IsNullOrEmpty(PackageName)) { continue; } Dictionary <string, string> FilesToInstall = new Dictionary <string, string>(); IOSBuild NewBuild = new IOSBuild(UnrealConfig, PackageName, SourceIPAPath, FilesToInstall, Flags); DiscoveredBuilds.Add(NewBuild); Log.Verbose("Found {0} {1} build at {2}", UnrealConfig, ((Flags & BuildFlags.Bulk) == BuildFlags.Bulk) ? "(bulk)" : "(not bulk)", AbsPath); } return(DiscoveredBuilds); }
public static IEnumerable <T> CreateFromPath <T>(UnrealTargetPlatform InPlatform, string InProjectName, string InPath, string InExecutableExtension) where T : StagedBuild { string BuildPath = InPath; List <T> DiscoveredBuilds = new List <T>(); // Turn FooGame into just Foo as we need to check for client/server builds too string ShortName = Regex.Replace(InProjectName, "Game", "", RegexOptions.IgnoreCase); string ContentPath = Path.Combine(InPath, InProjectName, "Content", "Paks"); if (Directory.Exists(ContentPath)) { string EngineBinaryPath = Path.Combine(InPath, "Engine", "Binaries", InPlatform.ToString()); string GameBinaryPath = Path.Combine(InPath, InProjectName, "Binaries", InPlatform.ToString()); // Executable will either be Project*.exe or for content-only UE4Game.exe string[] ExecutableMatches = new string[] { ShortName + "*" + InExecutableExtension, "UE4Game*" + InExecutableExtension, }; // check // 1) Path/Project/Binaries/Platform // 2) Path (content only builds on some platforms write out a stub exe here) // 3) path/Engine/Binaries/Platform string[] ExecutablePaths = new string[] { Path.Combine(InPath, InProjectName, "Binaries", InPlatform.ToString()), Path.Combine(InPath), Path.Combine(InPath, "Engine", "Binaries", InPlatform.ToString()), }; List <FileSystemInfo> Binaries = new List <FileSystemInfo>(); foreach (var BinaryPath in ExecutablePaths) { if (Directory.Exists(BinaryPath)) { DirectoryInfo Di = new DirectoryInfo(BinaryPath); foreach (var FileMatch in ExecutableMatches) { // Look at files & directories since apps on Mac are bundles FileSystemInfo[] AppFiles = Di.GetFileSystemInfos(FileMatch); Binaries.AddRange(AppFiles); } } } foreach (FileSystemInfo App in Binaries) { UnrealTargetConfiguration Config = UnrealHelpers.GetConfigurationFromExecutableName(InProjectName, App.Name); UnrealTargetRole Role = UnrealHelpers.GetRoleFromExecutableName(InProjectName, App.Name); if (Config != UnrealTargetConfiguration.Unknown && Role != UnrealTargetRole.Unknown) { // store the exe path as relative to the staged dir path T NewBuild = Activator.CreateInstance(typeof(T), new object[] { InPlatform, Config, Role, InPath, Utils.SystemHelpers.MakePathRelative(App.FullName, InPath) }) as T; if (App.Name.StartsWith("UE4Game", StringComparison.OrdinalIgnoreCase)) { NewBuild.Flags |= BuildFlags.ContentOnlyProject; } DiscoveredBuilds.Add(NewBuild); } } } return(DiscoveredBuilds); }
public static IEnumerable <LuminBuild> CreateFromPath(string InProjectName, string InPath) { string BuildPath = InPath; List <LuminBuild> DiscoveredBuilds = new List <LuminBuild>(); DirectoryInfo Di = new DirectoryInfo(BuildPath); if (Di.Exists) { // find all install batchfiles FileInfo[] InstallFiles = Di.GetFiles("Install_*"); foreach (FileInfo Fi in InstallFiles) { Log.Verbose("Pulling install data from {0}", Fi.FullName); string AbsPath = Fi.Directory.FullName; // read contents and replace linefeeds (regex doesn't stop on them :(( string BatContents = File.ReadAllText(Fi.FullName).Replace(Environment.NewLine, "\n"); // Replace .bat with .mpk and strip up to and including the first _, that is then our MPK name string SourceMpkPath = Regex.Replace(Fi.Name, ".bat", ".mpk", RegexOptions.IgnoreCase); SourceMpkPath = SourceMpkPath.Substring(SourceMpkPath.IndexOf("_") + 1); SourceMpkPath = Path.Combine(AbsPath, SourceMpkPath); Match Info = Regex.Match(BatContents, @"install\s+(-u+)\s""%~dp0\\(.+)"""); string LuminPackageName = Info.Groups[2].ToString(); if (string.IsNullOrEmpty(SourceMpkPath)) { Log.Warning("No MPK found for build at {0}", Fi.FullName); continue; } if (string.IsNullOrEmpty(LuminPackageName)) { Log.Warning("No product name found for build at {0}", Fi.FullName); continue; } UnrealTargetConfiguration UnrealConfig = UnrealHelpers.GetConfigurationFromExecutableName(InProjectName, Fi.Name); // Lumin builds are always packaged, and we can always replace the command line BuildFlags Flags = BuildFlags.Packaged | BuildFlags.CanReplaceCommandLine; if (AbsPath.Contains("Bulk")) { Flags |= BuildFlags.Bulk; } else { Flags |= BuildFlags.NotBulk; } LuminBuild NewBuild = new LuminBuild(UnrealConfig, LuminPackageName, SourceMpkPath, Flags); DiscoveredBuilds.Add(NewBuild); Log.Verbose("Found {0} {1} build at {2}", UnrealConfig, ((Flags & BuildFlags.Bulk) == BuildFlags.Bulk) ? "(bulk)" : "(not bulk)", AbsPath); } } return(DiscoveredBuilds); }
public static IEnumerable <AndroidBuild> CreateFromPath(string InProjectName, string InPath) { string BuildPath = InPath; List <AndroidBuild> DiscoveredBuilds = new List <AndroidBuild>(); DirectoryInfo Di = new DirectoryInfo(BuildPath); // find all install batchfiles FileInfo[] InstallFiles = Di.GetFiles("Install_*"); foreach (FileInfo Fi in InstallFiles) { bool PackageIs32Bit = Fi.FullName.Contains("armv7"); UnrealTargetConfiguration UnrealConfig = UnrealHelpers.GetConfigurationFromExecutableName(InProjectName, Fi.FullName); UnrealTargetRole UnrealRole = UnrealHelpers.GetRoleFromExecutableName(InProjectName, Fi.FullName); if (UnrealConfig == UnrealTargetConfiguration.Unknown) { Log.Info("Skipping unrecognized build {0}", Fi.FullName); continue; } bool TestInstall = Fi.Name.EndsWith("_TEST.bat", StringComparison.OrdinalIgnoreCase); bool PatchInstall = Fi.Name.EndsWith("_Patch.bat", StringComparison.OrdinalIgnoreCase); // filter out non-matching or test installation batch files // test installation scripts are intended to be manually invoked if (TestInstall || PatchInstall) { if (TestInstall || PatchInstall) { Log.Verbose("Ignoring {0} installation batch file {1}", TestInstall ? "test" : "patch", Fi.Name); } continue; } Log.Verbose("Pulling install data from {0}", Fi.FullName); string AbsPath = Fi.Directory.FullName; // read contents and replace linefeeds (regex doesn't stop on them :(( string BatContents = File.ReadAllText(Fi.FullName).Replace(Environment.NewLine, "\n"); // Replace .bat with .apk and strip up to and including the first _, that is then our APK name var SourceApkMatch = Regex.Match(BatContents, @" install\s+(.+\.apk)"); if (SourceApkMatch.Groups.Count <= 0) { Log.Warning("Could not parse install command from {0}", Fi.FullName); continue; } string SourceApkPath = Path.Combine(AbsPath, SourceApkMatch.Groups[1].ToString()); // save com.companyname.product string AndroidPackageName = Regex.Match(BatContents, @"uninstall\s+(com\..+)").Groups[1].ToString(); // pull all OBBs (probably just one..) var OBBMatches = Regex.Matches(BatContents, @"push\s+(.+?)\s+(.+)"); // save them as a dict of full paths as keys and dest paths as values Dictionary <string, string> FilesToInstall = OBBMatches.Cast <Match>().ToDictionary(M => Path.Combine(AbsPath, M.Groups[1].ToString()), M => M.Groups[2].ToString()); if (string.IsNullOrEmpty(SourceApkPath)) { Log.Warning("No APK found for build at {0}", Fi.FullName); continue; } if (!File.Exists(SourceApkPath)) { Log.Warning("Resolved APK name but it doesn't exist {0}", SourceApkPath); continue; } if (string.IsNullOrEmpty(AndroidPackageName)) { Log.Warning("No product name found for build at {0}", Fi.FullName); continue; } // Android builds are always packaged, and we can always replace the command line BuildFlags Flags = BuildFlags.Packaged | BuildFlags.CanReplaceCommandLine; // if there's data then the pak files are in an obb and we can sub in a new exe if (FilesToInstall.Count() > 0) { Flags |= BuildFlags.CanReplaceExecutable; } if (AbsPath.Contains("Bulk")) { Flags |= BuildFlags.Bulk; } else { Flags |= BuildFlags.NotBulk; } AndroidBuild NewBuild = new AndroidBuild(UnrealConfig, AndroidPackageName, SourceApkPath, FilesToInstall, Flags, PackageIs32Bit); DiscoveredBuilds.Add(NewBuild); Log.Verbose("Found {0} {1} build at {2}", UnrealConfig, ((Flags & BuildFlags.Bulk) == BuildFlags.Bulk) ? "(bulk)" : "(not bulk)", AbsPath); } // If we have both 32 and 64-bit builds, prefer 64-bit if (DiscoveredBuilds.Where(B => B.Is32Bit == false).Any()) { DiscoveredBuilds = DiscoveredBuilds.Where(B => !B.Is32Bit).ToList(); } return(DiscoveredBuilds); }