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);
        }
Esempio n. 2
0
        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);
        }