// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml; using AutomationTool; using UnrealBuildBase; using Microsoft.Extensions.Logging; [Help(@"Pulls a value from an ini file and inserts it into a plist.")] [Help(@"Note currently only looks at values irrespective of sections!")] [Help("IniFile=", @"Path to ini file to read from")] [Help("IniProperty=", @"Name of the ini property to read. E.g. 'Version' for 'Version=12.0'")] [Help("PlistFile=", @"Path to plist file to update")] [Help("PlistProperty=", @"Plist property to update. E.g. CFBundleShortVersionString")] public class WriteIniValueToPlist : BuildCommand { /// /// Path to the ini file to be read /// protected string IniFile { get; set; } /// /// Ini property to read /// protected string IniProperty { get; set; } /// /// Path to the plist file to be updated /// protected string PlistFile { get; set; } /// /// Plist property to update /// protected string PlistProperty { get; set; } /// /// UAT command entry point /// /// public override ExitCode Execute() { // Temp - wrap everything in an exception handler to avoid taking down Fortnite // builds if something isn't handled :) try { IniFile = ParseParamValue("IniFile", IniFile); PlistFile = ParseParamValue("PlistFile", PlistFile); IniProperty = ParseParamValue("IniProperty", IniProperty); PlistProperty = ParseParamValue("PlistProperty", PlistProperty); if (!File.Exists(IniFile)) { throw new AutomationException("Must provide a valid ini file with -inifile"); } if (!File.Exists(PlistFile)) { throw new AutomationException("Must provide a valid plist file with -PlistFile"); } if (string.IsNullOrEmpty(IniProperty)) { throw new AutomationException("Must provide a valid ini property -IniProperty"); } if (string.IsNullOrEmpty(PlistProperty)) { throw new AutomationException("Must provide a valid plist property -PlistProperty"); } // Read the ini file string IniFileContents = File.ReadAllText(IniFile); string IniPattern = string.Format(@"{0}\s*=(.+)", IniProperty); Match IniMatch = Regex.Match(IniFileContents, IniPattern, RegexOptions.IgnoreCase); if (IniMatch.Success == false) { throw new AutomationException("Unable to find ini value for property {0}. (Match pattern = {1})", IniProperty, IniPattern); } string IniValue = IniMatch.Groups[1].ToString().Trim(); Logger.LogInformation("Found ini value {IniValue} for property {IniProperty}", IniValue, IniProperty); string PlistFileContents = File.ReadAllText(PlistFile); string PlistPattern = string.Format(@"{0}\s*<.+?>(.+)<.+?>", PlistProperty); Match PlistMatch = Regex.Match(PlistFileContents, PlistPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline); if (PlistMatch.Success == false) { throw new AutomationException("Unable to find plist entry for property {0}. (Match pattern = {1})", PlistProperty, PlistPattern); } // the whole entry is group0 so replace the value of its current entry with the ini value string PListEntry = PlistMatch.Groups[0].ToString(); string PListValue = PlistMatch.Groups[1].ToString(); Logger.LogInformation("Found existing value {PListValue} for plist entry {PlistProperty}", PListValue, PlistProperty); string NewPlistEntry = PListEntry.Replace(PListValue, IniValue); Logger.LogInformation("Set entry {PlistProperty} to {IniValue}", PlistProperty, IniValue); PlistFileContents = PlistFileContents.Replace(PListEntry, NewPlistEntry); Logger.LogInformation("Saving new plist to {PlistFile}", PlistFile); File.WriteAllText(PlistFile, PlistFileContents); Logger.LogInformation("Done"); } catch (Exception Ex) { Logger.LogWarning("Failed to update plist {PlistFile}. {Ex}", PlistFile, Ex); } return ExitCode.Success; } }