/// <summary>
 /// Merge another manifest into this one
 /// </summary>
 /// <param name="Other">The manifest to merge in</param>
 public void Include(ModuleManifest Other)
 {
     foreach (KeyValuePair <string, string> Pair in Other.ModuleNameToFileName)
     {
         if (!ModuleNameToFileName.ContainsKey(Pair.Key))
         {
             ModuleNameToFileName.Add(Pair.Key, Pair.Value);
         }
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Merge a manifest into another manifest
 /// </summary>
 /// <param name="SourceManifest">The source manifest</param>
 /// <param name="TargetManifest">The target manifest to merge into</param>
 static void MergeManifests(ModuleManifest SourceManifest, ModuleManifest TargetManifest)
 {
     foreach (KeyValuePair <string, string> ModulePair in SourceManifest.ModuleNameToFileName)
     {
         if (!TargetManifest.ModuleNameToFileName.ContainsKey(ModulePair.Key))
         {
             TargetManifest.ModuleNameToFileName.Add(ModulePair.Key, ModulePair.Value);
         }
     }
 }
        /// <summary>
        /// Read an app receipt from disk
        /// </summary>
        /// <param name="FileName">Filename to read from</param>
        /// <returns>The receipt that was read</returns>
        public static ModuleManifest Read(FileReference FileName)
        {
            JsonObject Object = JsonObject.Read(FileName);

            ModuleManifest Receipt = new ModuleManifest(Object.GetStringField("BuildId"));

            JsonObject Modules = Object.GetObjectField("Modules");

            foreach (string ModuleName in Modules.KeyNames)
            {
                Receipt.ModuleNameToFileName.Add(ModuleName, Modules.GetStringField(ModuleName));
            }
            return(Receipt);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Checks whether a module manifest on disk is out of date (whether any of the binaries it references are newer than it is)
        /// </summary>
        /// <param name="ManifestFileName">Path to the manifest</param>
        /// <param name="Manifest">The manifest contents</param>
        /// <returns>True if the manifest is out of date</returns>
        bool IsOutOfDate(FileReference ManifestFileName, ModuleManifest Manifest)
        {
            DateTime ManifestTime = FileReference.GetLastWriteTimeUtc(ManifestFileName);

            foreach (string FileName in Manifest.ModuleNameToFileName.Values)
            {
                FileInfo ModuleInfo = new FileInfo(FileReference.Combine(ManifestFileName.Directory, FileName).FullName);
                if (!ModuleInfo.Exists || ModuleInfo.LastWriteTimeUtc > ManifestTime)
                {
                    return(true);
                }
            }
            return(false);
        }
 /// <summary>
 /// Tries to read a receipt from disk.
 /// </summary>
 /// <param name="FileName">The filename that was read</param>
 /// <param name="Result">If successful, the receipt that was read. Null otherwise.</param>
 /// <returns>True if the file was read succesfully.</returns>
 public static bool TryRead(FileReference FileName, out ModuleManifest Result)
 {
     if (!FileReference.Exists(FileName))
     {
         Result = null;
         return(false);
     }
     try
     {
         Result = Read(FileName);
         return(true);
     }
     catch (Exception)
     {
         Result = null;
         return(false);
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Attempts to read a manifest from the given location
        /// </summary>
        /// <param name="ManifestFileName">Path to the manifest</param>
        /// <param name="Manifest">If successful, receives the manifest that was read</param>
        /// <returns>True if the manifest was read correctly, false otherwise</returns>
        public static bool TryReadManifest(FileReference ManifestFileName, out ModuleManifest Manifest)
        {
            if (FileReference.Exists(ManifestFileName))
            {
                try
                {
                    Manifest = ModuleManifest.Read(ManifestFileName);
                    return(true);
                }
                catch (Exception Ex)
                {
                    Log.TraceWarning("Unable to read '{0}'; ignoring.", ManifestFileName);
                    Log.TraceLog(ExceptionUtils.FormatExceptionDetails(Ex));
                }
            }

            Manifest = null;
            return(false);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Execute the command, having obtained the appropriate mutex
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        private int ExecuteInternal(CommandLineArguments Arguments)
        {
            // Read the target info
            WriteMetadataTargetInfo TargetInfo = BinaryFormatterUtils.Load <WriteMetadataTargetInfo>(Arguments.GetFileReference("-Input="));
            bool bNoManifestChanges            = Arguments.HasOption("-NoManifestChanges");
            int  VersionNumber = Arguments.GetInteger("-Version=");

            Arguments.CheckAllArgumentsUsed();

            // Make sure the version number is correct
            if (VersionNumber != CurrentVersionNumber)
            {
                throw new BuildException("Version number to WriteMetadataMode is incorrect (expected {0}, got {1})", CurrentVersionNumber, VersionNumber);
            }

            // Check if we need to set a build id
            TargetReceipt Receipt = TargetInfo.Receipt;

            if (String.IsNullOrEmpty(Receipt.Version.BuildId))
            {
                // Check if there's an existing version file. If it exists, try to merge in any manifests that are valid (and reuse the existing build id)
                BuildVersion PreviousVersion;
                if (TargetInfo.VersionFile != null && BuildVersion.TryRead(TargetInfo.VersionFile, out PreviousVersion))
                {
                    // Check if we can reuse the existing manifests. This prevents unnecessary builds when switching between projects.
                    Dictionary <FileReference, ModuleManifest> PreviousFileToManifest = new Dictionary <FileReference, ModuleManifest>();
                    if (TryRecyclingManifests(PreviousVersion.BuildId, TargetInfo.FileToManifest.Keys, PreviousFileToManifest))
                    {
                        // Merge files from the existing manifests with the new ones
                        foreach (KeyValuePair <FileReference, ModuleManifest> Pair in PreviousFileToManifest)
                        {
                            ModuleManifest TargetManifest = TargetInfo.FileToManifest[Pair.Key];
                            MergeManifests(Pair.Value, TargetManifest);
                        }

                        // Update the build id to use the current one
                        Receipt.Version.BuildId = PreviousVersion.BuildId;
                    }
                }

                // If the build id is still not set, generate a new one from a GUID
                if (String.IsNullOrEmpty(Receipt.Version.BuildId))
                {
                    Receipt.Version.BuildId = Guid.NewGuid().ToString();
                }
            }
            else
            {
                // Read all the manifests and merge them into the new ones, if they have the same build id
                foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
                {
                    ModuleManifest SourceManifest;
                    if (TryReadManifest(Pair.Key, out SourceManifest) && SourceManifest.BuildId == Receipt.Version.BuildId)
                    {
                        MergeManifests(SourceManifest, Pair.Value);
                    }
                }
            }

            // Update the build id in all the manifests, and write them out
            foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
            {
                FileReference ManifestFile = Pair.Key;
                if (!UnrealBuildTool.IsFileInstalled(ManifestFile))
                {
                    ModuleManifest Manifest = Pair.Value;
                    Manifest.BuildId = Receipt.Version.BuildId;

                    if (!FileReference.Exists(ManifestFile))
                    {
                        // If the file doesn't already exist, just write it out
                        DirectoryReference.CreateDirectory(ManifestFile.Directory);
                        Manifest.Write(ManifestFile);
                    }
                    else
                    {
                        // Otherwise write it to a buffer first
                        string OutputText;
                        using (StringWriter Writer = new StringWriter())
                        {
                            Manifest.Write(Writer);
                            OutputText = Writer.ToString();
                        }

                        // And only write it to disk if it's been modified. Note that if a manifest is out of date, we should have generated a new build id causing the contents to differ.
                        string CurrentText = FileReference.ReadAllText(ManifestFile);
                        if (CurrentText != OutputText)
                        {
                            if (bNoManifestChanges)
                            {
                                Log.TraceError("Build modifies {0}. This is not permitted. Before:\n    {1}\nAfter:\n    {2}", ManifestFile, CurrentText.Replace("\n", "\n    "), OutputText.Replace("\n", "\n    "));
                            }
                            else
                            {
                                FileReference.WriteAllText(ManifestFile, OutputText);
                            }
                        }
                    }
                }
            }

            // Write out the version file, if it's changed. Since this file is next to the executable, it may be used by multiple targets, and we should avoid modifying it unless necessary.
            if (TargetInfo.VersionFile != null && !UnrealBuildTool.IsFileInstalled(TargetInfo.VersionFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.VersionFile.Directory);

                StringWriter Writer = new StringWriter();
                Receipt.Version.Write(Writer);

                string Text = Writer.ToString();
                if (!FileReference.Exists(TargetInfo.VersionFile) || File.ReadAllText(TargetInfo.VersionFile.FullName) != Text)
                {
                    File.WriteAllText(TargetInfo.VersionFile.FullName, Text);
                }
            }

            // Write out the receipt
            if (!UnrealBuildTool.IsFileInstalled(TargetInfo.ReceiptFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.ReceiptFile.Directory);
                Receipt.Write(TargetInfo.ReceiptFile);
            }

            return(0);
        }