public bool Matches(P4ClientInfo Other) { return Name == Other.Name && RootPath == Other.RootPath && Host == Other.Host && Owner == Other.Owner && LineEnd == Other.LineEnd && Options == Other.Options && SubmitOptions == Other.SubmitOptions && Enumerable.SequenceEqual(View, Other.View); }
public bool Matches(P4ClientInfo Other) { return Name == Other.Name && RootPath == Other.RootPath && Host == Other.Host && Owner == Other.Owner && Stream == Other.Stream && LineEnd == Other.LineEnd && Options == Other.Options && SubmitOptions == Other.SubmitOptions && (!String.IsNullOrEmpty(Stream) || Enumerable.SequenceEqual(View, Other.View)); }
/// <summary> /// Detects root paths for the specified client. /// </summary> /// <param name="UATLocation">AutomationTool.exe location</param> /// <param name="ThisClient">Client to detect the root paths for</param> /// <param name="BuildRootPath">Build root</param> /// <param name="LocalRootPath">Local root</param> /// <param name="ClientRootPath">Client root</param> private static void DetectRootPaths(P4Connection Connection, string LocalRootPath, P4ClientInfo ThisClient, out string BuildRootPath, out string ClientRootPath) { if(!String.IsNullOrEmpty(ThisClient.Stream)) { BuildRootPath = ThisClient.Stream; ClientRootPath = String.Format("//{0}", ThisClient.Name); } else { // Figure out the build root string KnownFilePathFromRoot = CommandEnvironment.KnownFileRelativeToRoot; string KnownLocalPath = CommandUtils.MakePathSafeToUseWithCommandLine(CommandUtils.CombinePaths(PathSeparator.Slash, LocalRootPath, KnownFilePathFromRoot)); IProcessResult P4Result = Connection.P4(String.Format("files -m 1 {0}", KnownLocalPath), AllowSpew: false); string KnownFileDepotMapping = P4Result.Output; // Get the build root Log.TraceVerbose("Looking for {0} in {1}", KnownFilePathFromRoot, KnownFileDepotMapping); int EndIdx = KnownFileDepotMapping.IndexOf(KnownFilePathFromRoot, StringComparison.CurrentCultureIgnoreCase); if (EndIdx < 0) { EndIdx = KnownFileDepotMapping.IndexOf(CommandUtils.ConvertSeparators(PathSeparator.Slash, KnownFilePathFromRoot), StringComparison.CurrentCultureIgnoreCase); } // Get the root path without the trailing path separator BuildRootPath = KnownFileDepotMapping.Substring(0, EndIdx - 1); // Get the client root if (LocalRootPath.StartsWith(CommandUtils.CombinePaths(PathSeparator.Slash, ThisClient.RootPath, "/"), StringComparison.InvariantCultureIgnoreCase) || LocalRootPath == CommandUtils.CombinePaths(PathSeparator.Slash, ThisClient.RootPath)) { ClientRootPath = CommandUtils.CombinePaths(PathSeparator.Depot, String.Format("//{0}/", ThisClient.Name), LocalRootPath.Substring(ThisClient.RootPath.Length)); } else { throw new AutomationException("LocalRootPath ({0}) does not start with the client root path ({1})", LocalRootPath, ThisClient.RootPath); } } }
/// <summary> /// Gets client info (does not check if the client exists) /// </summary> /// <param name="ClientName">Name of the client.</param> /// <returns></returns> public static P4ClientInfo GetClientInfoInternal(string ClientName) { P4ClientInfo Info = new P4ClientInfo(); var P4Result = CommandUtils.P4(String.Format("client -o {0}", ClientName), AllowSpew: false); if (P4Result == 0) { var Tags = ParseTaggedP4Output(P4Result.Output); Info.Name = ClientName; Tags.TryGetValue("Host", out Info.Host); Tags.TryGetValue("Root", out Info.RootPath); if (!String.IsNullOrEmpty(Info.RootPath)) { Info.RootPath = ConvertSeparators(PathSeparator.Default, Info.RootPath); } Tags.TryGetValue("Owner", out Info.Owner); string AccessTime; Tags.TryGetValue("Access", out AccessTime); if (!String.IsNullOrEmpty(AccessTime)) { DateTime.TryParse(AccessTime, out Info.Access); } else { Info.Access = DateTime.MinValue; } string LineEnd; Tags.TryGetValue("LineEnd", out LineEnd); if (!String.IsNullOrEmpty(LineEnd)) { Info.LineEnd = (P4LineEnd)ParseEnumValues(LineEnd, typeof(P4LineEnd)); } string ClientOptions; Tags.TryGetValue("Options", out ClientOptions); if (!String.IsNullOrEmpty(ClientOptions)) { Info.Options = (P4ClientOption)ParseEnumValues(ClientOptions, typeof(P4ClientOption)); } string SubmitOptions; Tags.TryGetValue("SubmitOptions", out SubmitOptions); if (!String.IsNullOrEmpty(SubmitOptions)) { Info.SubmitOptions = (P4SubmitOption)ParseEnumValues(SubmitOptions, typeof(P4SubmitOption)); } string ClientMappingRoot = "//" + ClientName; foreach (var Pair in Tags) { if (Pair.Key.StartsWith("View", StringComparison.InvariantCultureIgnoreCase)) { string Mapping = Pair.Value; int ClientStartIndex = Mapping.IndexOf(ClientMappingRoot, StringComparison.InvariantCultureIgnoreCase); if (ClientStartIndex > 0) { var ViewPair = new KeyValuePair<string, string>( Mapping.Substring(0, ClientStartIndex - 1), Mapping.Substring(ClientStartIndex + ClientMappingRoot.Length)); Info.View.Add(ViewPair); } } } } else { throw new AutomationException("p4 client -o {0} failed!", ClientName); } return Info; }
/// <summary> /// Creates a new client. /// </summary> /// <param name="ClientSpec">Client specification.</param> /// <returns></returns> public P4ClientInfo CreateClient(P4ClientInfo ClientSpec) { string SpecInput = "Client: " + ClientSpec.Name + Environment.NewLine; SpecInput += "Owner: " + ClientSpec.Owner + Environment.NewLine; SpecInput += "Host: " + ClientSpec.Host + Environment.NewLine; SpecInput += "Root: " + ClientSpec.RootPath + Environment.NewLine; SpecInput += "Options: " + ClientSpec.Options.ToString().ToLowerInvariant().Replace(",", "") + Environment.NewLine; SpecInput += "SubmitOptions: " + ClientSpec.SubmitOptions.ToString().ToLowerInvariant().Replace(",", "") + Environment.NewLine; SpecInput += "LineEnd: " + ClientSpec.LineEnd.ToString().ToLowerInvariant() + Environment.NewLine; SpecInput += "View:" + Environment.NewLine; foreach (var Mapping in ClientSpec.View) { SpecInput += "\t" + Mapping.Key + " //" + ClientSpec.Name + Mapping.Value + Environment.NewLine; } Log(SpecInput); LogP4("client -i", SpecInput); return ClientSpec; }
public override void ExecuteBuild() { // Parse the target list string[] Targets = ParseParamValues("Target"); if(Targets.Length == 0) { throw new AutomationException("No targets specified (eg. -Target=\"UE4Editor Win64 Development\")"); } // Parse the archive path string ArchivePath = ParseParamValue("Archive"); if(ArchivePath != null && (!ArchivePath.StartsWith("//") || ArchivePath.Sum(x => (x == '/')? 1 : 0) < 4)) { throw new AutomationException("Archive path is not a valid depot filename"); } // Prepare the build agenda UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda(); foreach(string Target in Targets) { string[] Tokens = Target.Split(new char[]{ ' ' }, StringSplitOptions.RemoveEmptyEntries); UnrealTargetPlatform Platform; UnrealTargetConfiguration Configuration; if(Tokens.Length < 3 || !Enum.TryParse(Tokens[1], true, out Platform) || !Enum.TryParse(Tokens[2], true, out Configuration)) { throw new AutomationException("Invalid target '{0}' - expected <TargetName> <Platform> <Configuration>"); } Agenda.AddTarget(Tokens[0], Platform, Configuration, InAddArgs: String.Join(" ", Tokens.Skip(3))); } // Build everything UE4Build Builder = new UE4Build(this); Builder.Build(Agenda, InUpdateVersionFiles: ArchivePath != null); // Include the build products for UAT and UBT if required if(ParseParam("WithUAT")) { Builder.AddUATFilesToBuildProducts(); } if(ParseParam("WithUBT")) { Builder.AddUBTFilesToBuildProducts(); } // Archive the build products if(ArchivePath != null) { // Create an output folder string OutputFolder = Path.Combine(CommandUtils.CmdEnv.LocalRoot, "ArchiveForUGS"); Directory.CreateDirectory(OutputFolder); // Create a temp folder for storing stripped PDB files string SymbolsFolder = Path.Combine(OutputFolder, "Symbols"); Directory.CreateDirectory(SymbolsFolder); // Get the Windows toolchain UEToolChain WindowsToolChain = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Win64).CreateContext(null).CreateToolChain(CPPTargetPlatform.Win64); // Figure out all the files for the archive Ionic.Zip.ZipFile Zip = new Ionic.Zip.ZipFile(); Zip.UseZip64WhenSaving = Ionic.Zip.Zip64Option.Always; foreach(string BuildProduct in Builder.BuildProductFiles) { if(!File.Exists(BuildProduct)) { throw new AutomationException("Missing build product: {0}", BuildProduct); } if(BuildProduct.EndsWith(".pdb", StringComparison.InvariantCultureIgnoreCase)) { string StrippedFileName = CommandUtils.MakeRerootedFilePath(BuildProduct, CommandUtils.CmdEnv.LocalRoot, SymbolsFolder); Directory.CreateDirectory(Path.GetDirectoryName(StrippedFileName)); WindowsToolChain.StripSymbols(BuildProduct, StrippedFileName); Zip.AddFile(StrippedFileName, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(StrippedFileName, SymbolsFolder))); } else { Zip.AddFile(BuildProduct, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(BuildProduct, CommandUtils.CmdEnv.LocalRoot))); } } // Create the zip file string ZipFileName = Path.Combine(OutputFolder, "Archive.zip"); Console.WriteLine("Writing {0}...", ZipFileName); Zip.Save(ZipFileName); // Submit it to Perforce if required if(CommandUtils.AllowSubmit) { // Delete any existing clientspec for submitting string ClientName = Environment.MachineName + "_BuildForUGS"; // Create a brand new one P4ClientInfo Client = new P4ClientInfo(); Client.Owner = CommandUtils.P4Env.User; Client.Host = Environment.MachineName; Client.Stream = ArchivePath.Substring(0, ArchivePath.IndexOf('/', ArchivePath.IndexOf('/', 2) + 1)); Client.RootPath = Path.Combine(OutputFolder, "Perforce"); Client.Name = ClientName; Client.Options = P4ClientOption.NoAllWrite | P4ClientOption.NoClobber | P4ClientOption.NoCompress | P4ClientOption.Unlocked | P4ClientOption.NoModTime | P4ClientOption.RmDir; Client.LineEnd = P4LineEnd.Local; P4.CreateClient(Client, AllowSpew: false); // Create a new P4 connection for this workspace P4Connection SubmitP4 = new P4Connection(Client.Owner, Client.Name, P4Env.P4Port); SubmitP4.Revert("-k //..."); // Figure out where the zip file has to go in Perforce P4WhereRecord WhereZipFile = SubmitP4.Where(ArchivePath, false).FirstOrDefault(x => !x.bUnmap && x.Path != null); if(WhereZipFile == null) { throw new AutomationException("Couldn't locate {0} in this workspace"); } // Get the latest version of it int NewCL = SubmitP4.CreateChange(Description: String.Format("[CL {0}] Updated binaries", P4Env.Changelist)); SubmitP4.Sync(String.Format("-k \"{0}\"", ArchivePath), AllowSpew:false); CommandUtils.CopyFile(ZipFileName, WhereZipFile.Path); SubmitP4.Add(NewCL, String.Format("\"{0}\"", ArchivePath)); SubmitP4.Edit(NewCL, String.Format("\"{0}\"", ArchivePath)); // Submit it int SubmittedCL; SubmitP4.Submit(NewCL, out SubmittedCL); if(SubmittedCL <= 0) { throw new AutomationException("Submit failed."); } Console.WriteLine("Submitted in changelist {0}", SubmittedCL); } } }
/// <summary> /// Creates a new client. /// </summary> /// <param name="ClientSpec">Client specification.</param> /// <returns></returns> public P4ClientInfo CreateClient(P4ClientInfo ClientSpec, bool AllowSpew = true) { string SpecInput = "Client: " + ClientSpec.Name + Environment.NewLine; SpecInput += "Owner: " + ClientSpec.Owner + Environment.NewLine; SpecInput += "Host: " + ClientSpec.Host + Environment.NewLine; SpecInput += "Root: " + ClientSpec.RootPath + Environment.NewLine; SpecInput += "Options: " + ClientSpec.Options.ToString().ToLowerInvariant().Replace(",", "") + Environment.NewLine; SpecInput += "SubmitOptions: " + ClientSpec.SubmitOptions.ToString().ToLowerInvariant().Replace(",", "") + Environment.NewLine; SpecInput += "LineEnd: " + ClientSpec.LineEnd.ToString().ToLowerInvariant() + Environment.NewLine; if(ClientSpec.Stream != null) { SpecInput += "Stream: " + ClientSpec.Stream + Environment.NewLine; } else { SpecInput += "View:" + Environment.NewLine; foreach (var Mapping in ClientSpec.View) { SpecInput += "\t" + Mapping.Key + " //" + ClientSpec.Name + Mapping.Value + Environment.NewLine; } } if (AllowSpew) CommandUtils.LogLog(SpecInput); LogP4("client -i", SpecInput, AllowSpew: AllowSpew, WithClient: false); return ClientSpec; }