/// <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) { // Figure out the build root string KnownFilePathFromRoot = CommandEnvironment.KnownFileRelativeToRoot; string KnownLocalPath = CommandUtils.MakePathSafeToUseWithCommandLine(CommandUtils.CombinePaths(PathSeparator.Slash, LocalRootPath, KnownFilePathFromRoot)); ProcessResult 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 == 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> /// Detects current user name. /// </summary> /// <returns></returns> private static string DetectUserName(P4Connection Connection) { var UserName = String.Empty; var P4Result = Connection.P4("info", AllowSpew: false); if (P4Result.ExitCode != 0) { throw new AutomationException("Perforce command failed: {0}. Please make sure your P4PORT or {1} is set properly.", P4Result.Output, EnvVarNames.P4Port); } // Retrieve the P4 user name var Tags = Connection.ParseTaggedP4Output(P4Result.Output); if (!Tags.TryGetValue("User name", out UserName) || String.IsNullOrEmpty(UserName)) { if (!String.IsNullOrEmpty(UserName)) { Log.TraceWarning("Unable to retrieve perforce user name. Trying to fall back to {0} which is set to {1}.", EnvVarNames.User, UserName); } else { throw new AutomationException("Failed to retrieve user name."); } } return(UserName); }
/// <summary> /// Detects the current code changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCodeCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CodeCL not set, detecting last code CL..."); // Retrieve the current changelist StringBuilder P4Cmd = new StringBuilder("changes -m 1"); string[] CodeExtensions = { ".cs", ".h", ".cpp", ".inl", ".usf", ".ush", ".uproject", ".uplugin" }; foreach (string CodeExtension in CodeExtensions) { P4Cmd.AppendFormat(" \"{0}/...{1}#have\"", CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath), CodeExtension); } IProcessResult P4Result = Connection.P4(P4Cmd.ToString(), AllowSpew: false); // Loop through all the lines of the output. Even though we requested one result, we'll get one for each search pattern. int CL = 0; foreach (string Line in P4Result.Output.Split('\n')) { string[] Tokens = Line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (Tokens.Length >= 2) { int LineCL = Int32.Parse(Tokens[1]); CL = Math.Max(CL, LineCL); } } return(CL.ToString()); }
protected virtual void InitEnvironment(P4Connection Connection, CommandEnvironment CmdEnv) { // // P4 Environment // P4Port = CommandUtils.GetEnvVar(EnvVarNames.P4Port); ClientRoot = CommandUtils.GetEnvVar(EnvVarNames.ClientRoot); User = CommandUtils.GetEnvVar(EnvVarNames.User); ChangelistStringInternal = CommandUtils.GetEnvVar(EnvVarNames.Changelist, null); Client = CommandUtils.GetEnvVar(EnvVarNames.Client); BuildRootP4 = CommandUtils.GetEnvVar(EnvVarNames.BuildRootP4); if (BuildRootP4.EndsWith("/", StringComparison.InvariantCultureIgnoreCase) || BuildRootP4.EndsWith("\\", StringComparison.InvariantCultureIgnoreCase)) { // We expect the build root to not end with a path separator BuildRootP4 = BuildRootP4.Substring(0, BuildRootP4.Length - 1); CommandUtils.SetEnvVar(EnvVarNames.BuildRootP4, BuildRootP4); } BuildRootEscaped = CommandUtils.GetEnvVar(EnvVarNames.BuildRootEscaped); LabelToSync = CommandUtils.GetEnvVar(EnvVarNames.LabelToSync); string CodeChangelistString = CommandUtils.GetEnvVar(EnvVarNames.CodeChangelist); if (!String.IsNullOrEmpty(CodeChangelistString)) { CodeChangelist = Int32.Parse(CodeChangelistString); } if (((CommandUtils.P4Enabled || CommandUtils.IsBuildMachine) && (ClientRoot == String.Empty || User == String.Empty || (String.IsNullOrEmpty(ChangelistStringInternal) && CommandUtils.IsBuildMachine) || Client == String.Empty || BuildRootP4 == String.Empty))) { Log.TraceInformation("P4Enabled={0}", CommandUtils.P4Enabled); Log.TraceInformation("ClientRoot={0}", ClientRoot); Log.TraceInformation("User={0}", User); Log.TraceInformation("ChangelistString={0}", ChangelistStringInternal); Log.TraceInformation("Client={0}", Client); Log.TraceInformation("BuildRootP4={0}", BuildRootP4); throw new AutomationException("BUILD FAILED Perforce Environment is not set up correctly. Please check your environment variables."); } LabelPrefix = BuildRootP4 + "/"; if (CommandUtils.P4Enabled) { if (CommandUtils.IsBuildMachine || ChangelistStringInternal != null) { // We may not always need the changelist number if we're not a build machine. // In local runs, changelist initialization can be really slow! VerifyChangelistStringAndSetChangelistNumber(); } } LogSettings(); }
protected virtual void InitEnvironment(P4Connection Connection, CommandEnvironment CmdEnv) { // // P4 Environment // P4Port = CommandUtils.GetEnvVar(EnvVarNames.P4Port); ClientRoot = CommandUtils.GetEnvVar(EnvVarNames.ClientRoot); User = CommandUtils.GetEnvVar(EnvVarNames.User); ChangelistStringInternal = CommandUtils.GetEnvVar(EnvVarNames.Changelist, null); Client = CommandUtils.GetEnvVar(EnvVarNames.Client); BuildRootP4 = CommandUtils.GetEnvVar(EnvVarNames.BuildRootP4); if (BuildRootP4.EndsWith("/", StringComparison.InvariantCultureIgnoreCase) || BuildRootP4.EndsWith("\\", StringComparison.InvariantCultureIgnoreCase)) { // We expect the build root to not end with a path separator BuildRootP4 = BuildRootP4.Substring(0, BuildRootP4.Length - 1); CommandUtils.SetEnvVar(EnvVarNames.BuildRootP4, BuildRootP4); } BuildRootEscaped = CommandUtils.GetEnvVar(EnvVarNames.BuildRootEscaped); LabelToSync = CommandUtils.GetEnvVar(EnvVarNames.LabelToSync); string CodeChangelistString = CommandUtils.GetEnvVar(EnvVarNames.CodeChangelist); if(!String.IsNullOrEmpty(CodeChangelistString)) { CodeChangelist = Int32.Parse(CodeChangelistString); } if (((CommandUtils.P4Enabled || CommandUtils.IsBuildMachine) && (ClientRoot == String.Empty || User == String.Empty || (String.IsNullOrEmpty(ChangelistStringInternal) && CommandUtils.IsBuildMachine) || Client == String.Empty || BuildRootP4 == String.Empty))) { Log.TraceInformation("P4Enabled={0}", CommandUtils.P4Enabled); Log.TraceInformation("ClientRoot={0}",ClientRoot ); Log.TraceInformation("User={0}", User); Log.TraceInformation("ChangelistString={0}", ChangelistStringInternal); Log.TraceInformation("Client={0}", Client); Log.TraceInformation("BuildRootP4={0}", BuildRootP4); throw new AutomationException("BUILD FAILED Perforce Environment is not set up correctly. Please check your environment variables."); } LabelPrefix = BuildRootP4 + "/"; if (CommandUtils.P4Enabled) { if (CommandUtils.IsBuildMachine || ChangelistStringInternal != null) { // We may not always need the changelist number if we're not a build machine. // In local runs, changelist initialization can be really slow! VerifyChangelistStringAndSetChangelistNumber(); } } LogSettings(); }
public override void ExecuteBuild() { // Parse the parameters string DepotPath = ParseParamValue("DepotPath"); if (DepotPath == null) { throw new AutomationException("Missing -DepotPath=... parameter"); } string OutputDir = ParseParamValue("OutputDir"); if (OutputDir == null) { throw new AutomationException("Missing -OutputDir=... parameter"); } // Create a temporary client to sync down the folder string ClientName = String.Format("{0}_{1}_SyncDepotPath_Temp", P4Env.User, Environment.MachineName); List <KeyValuePair <string, string> > RequiredView = new List <KeyValuePair <string, string> >(); RequiredView.Add(new KeyValuePair <string, string>(DepotPath, "/...")); if (P4.DoesClientExist(ClientName)) { P4.DeleteClient(ClientName); } P4ClientInfo Client = new P4ClientInfo(); Client.Owner = P4Env.User; Client.Host = Environment.MachineName; Client.RootPath = OutputDir; Client.Name = ClientName; Client.View = RequiredView; Client.Stream = null; Client.Options = P4ClientOption.NoAllWrite | P4ClientOption.Clobber | P4ClientOption.NoCompress | P4ClientOption.Unlocked | P4ClientOption.NoModTime | P4ClientOption.RmDir; Client.LineEnd = P4LineEnd.Local; P4.CreateClient(Client); // Sync the workspace, then delete the client try { P4Connection Perforce = new P4Connection(P4Env.User, ClientName); Perforce.Sync("-f //..."); } finally { P4.DeleteClient(ClientName); } }
/// <summary> /// Detects a workspace given the current user name, host name and depot path. /// </summary> /// <param name="UserName">User name</param> /// <param name="HostName">Host</param> /// <param name="UATLocation">Path to UAT exe, this will be checked agains the root path.</param> /// <returns>Client to use.</returns> private static P4ClientInfo DetectClient(P4Connection Connection, string UserName, string HostName, string UATLocation) { CommandUtils.LogVerbose("uebp_CLIENT not set, detecting current client..."); var MatchingClients = new List <P4ClientInfo>(); P4ClientInfo[] P4Clients = Connection.GetClientsForUser(UserName, UATLocation); foreach (var Client in P4Clients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) != 0) { Log.TraceInformation("Rejecting client because of different Host {0} \"{1}\" != \"{2}\"", Client.Name, Client.Host, HostName); continue; } MatchingClients.Add(Client); } P4ClientInfo ClientToUse = null; if (MatchingClients.Count == 0) { throw new AutomationException("No matching clientspecs found!"); } else if (MatchingClients.Count == 1) { ClientToUse = MatchingClients[0]; } else { // We may have empty host clients here, so pick the first non-empty one if possible foreach (var Client in MatchingClients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) == 0) { ClientToUse = Client; break; } } if (ClientToUse == null) { Log.TraceWarning("{0} clients found that match the current host and root path. The most recently accessed client will be used.", MatchingClients.Count); ClientToUse = GetMostRecentClient(MatchingClients); } } return(ClientToUse); }
/// <summary> /// Detects the current changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CL not set, detecting 'have' CL..."); // Retrieve the current changelist var P4Result = Connection.P4("changes -m 1 " + CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath, "/...#have"), AllowSpew: false); var CLTokens = P4Result.Output.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var CLString = CLTokens[1]; var CL = Int32.Parse(CLString); if (CLString != CL.ToString()) { throw new AutomationException("Failed to retrieve current changelist."); } return(CLString); }
/// <summary> /// Detects the current code changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCodeCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CodeCL not set, detecting last code CL..."); // Retrieve the current changelist string P4Cmd = String.Format("changes -m 1 \"{0}/....cpp#have\" \"{0}/....h#have\" \"{0}/....inl#have\" \"{0}/....cs#have\" \"{0}/....usf#have\"", CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath)); IProcessResult P4Result = Connection.P4(P4Cmd, AllowSpew: false); // Loop through all the lines of the output. Even though we requested one result, we'll get one for each search pattern. int CL = 0; foreach (string Line in P4Result.Output.Split('\n')) { string[] Tokens = Line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (Tokens.Length >= 2) { int LineCL = Int32.Parse(Tokens[1]); CL = Math.Max(CL, LineCL); } } return(CL.ToString()); }
/// <summary> /// Detects the current changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CL not set, detecting 'have' CL..."); // Retrieve the current changelist IProcessResult P4Result = Connection.P4("changes -m 1 " + CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath, "/...#have"), AllowSpew: false); string[] CLTokens = P4Result.Output.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (CLTokens.Length == 0) { throw new AutomationException("Unable to find current changelist (no output from 'p4 changes' command)"); } string CLString = CLTokens[1]; int CL; if (!Int32.TryParse(CLString, out CL) || CLString != CL.ToString()) { throw new AutomationException("Unable to parse current changelist from Perforce output:\n{0}", P4Result.Output); } return(CLString); }
/// <summary> /// Initializes the environment. Tries to autodetect all source control settings. /// </summary> /// <param name="CompilationEnv">Compilation environment</param> protected override void InitEnvironment(P4Connection Connection, CommandEnvironment CmdEnv) { var HostName = Environment.MachineName.ToLower(); var P4PortEnv = Environment.GetEnvironmentVariable("P4PORT"); if (String.IsNullOrEmpty(P4PortEnv)) { P4PortEnv = DetectP4Port(); } var UserName = CommandUtils.GetEnvVar(EnvVarNames.User); if (String.IsNullOrEmpty(UserName)) { UserName = DetectUserName(Connection); } var CommandLineClient = CommandUtils.GetEnvVar(EnvVarNames.Client); P4ClientInfo ThisClient = null; if (String.IsNullOrEmpty(CommandLineClient) == false) { ThisClient = Connection.GetClientInfo(CommandLineClient); if (ThisClient == null) { throw new AutomationException("Unable to find client {0}", CommandLineClient); } if (String.Compare(ThisClient.Owner, UserName, true) != 0) { throw new AutomationException("Client specified with {0}={1} has a different owner then the detected user name (has: {2}, expected: {3})", EnvVarNames.Client, CommandLineClient, ThisClient.Owner, UserName); } } else { ThisClient = DetectClient(Connection, UserName, HostName, CmdEnv.UATExe); } Log.TraceInformation("Using user {0} clientspec {1} {2}", UserName, ThisClient.Name, ThisClient.RootPath); Environment.SetEnvironmentVariable("P4CLIENT", ThisClient.Name); string BuildRootPath; string ClientRootPath; DetectRootPaths(Connection, CmdEnv.LocalRoot, ThisClient, out BuildRootPath, out ClientRootPath); CommandUtils.ConditionallySetEnvVar(EnvVarNames.P4Port, P4PortEnv); CommandUtils.ConditionallySetEnvVar(EnvVarNames.User, UserName); CommandUtils.ConditionallySetEnvVar(EnvVarNames.Client, ThisClient.Name); CommandUtils.ConditionallySetEnvVar(EnvVarNames.BuildRootP4, BuildRootPath); CommandUtils.ConditionallySetEnvVar(EnvVarNames.ClientRoot, ClientRootPath); var CLString = CommandUtils.GetEnvVar(EnvVarNames.Changelist, null); if (String.IsNullOrEmpty(CLString) && CommandUtils.P4CLRequired) { CLString = DetectCurrentCL(Connection, ClientRootPath); } if (!String.IsNullOrEmpty(CLString)) { CommandUtils.ConditionallySetEnvVar(EnvVarNames.Changelist, CLString); } CommandUtils.ConditionallySetEnvVar(EnvVarNames.LabelToSync, ""); CommandUtils.ConditionallySetEnvVar("P4USER", UserName); CommandUtils.ConditionallySetEnvVar("P4CLIENT", ThisClient.Name); var P4Password = Environment.GetEnvironmentVariable(EnvVarNames.P4Password); if (!String.IsNullOrEmpty(P4Password)) { CommandUtils.ConditionallySetEnvVar("P4PASSWD", P4Password); } SetBuildRootEscaped(); base.InitEnvironment(Connection, CmdEnv); }
internal LocalP4Environment(P4Connection Connection, CommandEnvironment CmdEnv) : base(Connection, CmdEnv) { }
/// <summary> /// Detects a workspace given the current user name, host name and depot path. /// </summary> /// <param name="UserName">User name</param> /// <param name="HostName">Host</param> /// <param name="UATLocation">Path to UAT exe, this will be checked agains the root path.</param> /// <returns>Client to use.</returns> private static P4ClientInfo DetectClient(P4Connection Connection, string UserName, string HostName, string UATLocation) { CommandUtils.LogVerbose("uebp_CLIENT not set, detecting current client..."); // Check the default client. If it matches we can save any guess work. IProcessResult Result = CommandUtils.Run(HostPlatform.Current.P4Exe, "set -q P4CLIENT", null, CommandUtils.ERunOptions.NoLoggingOfRunCommand); if (Result.ExitCode == 0) { const string KeyName = "P4CLIENT="; if (Result.Output.StartsWith(KeyName)) { string ClientName = Result.Output.Substring(KeyName.Length).Trim(); P4ClientInfo ClientInfo = Connection.GetClientInfo(ClientName, true); if (Connection.IsValidClientForFile(ClientInfo, UATLocation)) { return(ClientInfo); } } } // Otherwise search for all clients that match List <P4ClientInfo> MatchingClients = new List <P4ClientInfo>(); P4ClientInfo[] P4Clients = Connection.GetClientsForUser(UserName, UATLocation); foreach (P4ClientInfo Client in P4Clients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) != 0) { Log.TraceInformation("Rejecting client because of different Host {0} \"{1}\" != \"{2}\"", Client.Name, Client.Host, HostName); continue; } MatchingClients.Add(Client); } P4ClientInfo ClientToUse = null; if (MatchingClients.Count == 0) { throw new AutomationException("No matching clientspecs found!"); } else if (MatchingClients.Count == 1) { ClientToUse = MatchingClients[0]; } else { // We may have empty host clients here, so pick the first non-empty one if possible foreach (P4ClientInfo Client in MatchingClients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) == 0) { ClientToUse = Client; break; } } if (ClientToUse == null) { Log.TraceWarning("{0} clients found that match the current host and root path. The most recently accessed client will be used.", MatchingClients.Count); ClientToUse = GetMostRecentClient(MatchingClients); } } return(ClientToUse); }
/// <summary> /// Detects current user name. /// </summary> /// <returns></returns> private static string DetectUserName(P4Connection Connection) { var UserName = String.Empty; var P4Result = Connection.P4("info", AllowSpew: false); if (P4Result.ExitCode != 0) { throw new AutomationException("Perforce command failed: {0}. Please make sure your P4PORT or {1} is set properly.", P4Result.Output, EnvVarNames.P4Port); } // Retrieve the P4 user name var Tags = Connection.ParseTaggedP4Output(P4Result.Output); Tags.TryGetValue("User name", out UserName); if (String.IsNullOrEmpty(UserName)) { UserName = Environment.GetEnvironmentVariable(EnvVarNames.User); if (!String.IsNullOrEmpty(UserName)) { Log.TraceWarning("Unable to retrieve perforce user name. Trying to fall back to {0} which is set to {1}.", EnvVarNames.User, UserName); } else { throw new AutomationException("Failed to retrieve user name."); } } Environment.SetEnvironmentVariable("P4USER", UserName); return UserName; }
/// <summary> /// Initializes build environment. If the build command needs a specific env-var mapping or /// has an extended BuildEnvironment, it must implement this method accordingly. /// </summary> static internal void InitP4Environment() { CheckP4Enabled(); // Temporary connection - will use only the currently set env vars to connect to P4 var DefaultConnection = new P4Connection(User: null, Client: null); PerforceEnvironment = Automation.IsBuildMachine ? new P4Environment(DefaultConnection, CmdEnv) : new LocalP4Environment(DefaultConnection, CmdEnv); }
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> /// 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); } } }
public override void ExecuteBuild() { var Params = new ProjectParams ( Command: this, // Shared RawProjectPath: ProjectPath ); Log("********** CRYPTOKEYS COMMAND STARTED **********"); string UE4EditorExe = HostPlatform.Current.GetUE4ExePath(Params.UE4Exe); if (!FileExists(UE4EditorExe)) { throw new AutomationException("Missing " + UE4EditorExe + " executable. Needs to be built first."); } bool bCycleAllKeys = ParseParam("updateallkeys"); bool bCycleEncryptionKey = bCycleAllKeys || ParseParam("updateencryptionkey"); bool bCycleSigningKey = bCycleAllKeys || ParseParam("updatesigningkey"); if (!bCycleAllKeys && !bCycleEncryptionKey && !bCycleSigningKey) { throw new Exception("A target for key cycling must be specified when using the cryptokeys automation script\n\t-updateallkeys: Update all keys\n\t-updateencryptionkey: Update encryption key\n\t-updatesigningkey: Update signing key"); } FileReference OutputFile = FileReference.Combine(ProjectPath.Directory, "Config", "DefaultCrypto.ini"); FileReference NoRedistOutputFile = FileReference.Combine(ProjectPath.Directory, "Config", "NoRedist", "DefaultCrypto.ini"); FileReference DestinationFile = OutputFile; // If the project has a DefaultCrypto.ini in a NoRedist folder, we want to copy the newly generated file into that location if (FileReference.Exists(NoRedistOutputFile)) { DestinationFile = NoRedistOutputFile; } string ChangeDescription = "Automated update of "; if (bCycleEncryptionKey) { ChangeDescription += "encryption"; } if (bCycleSigningKey) { if (bCycleEncryptionKey) { ChangeDescription += " and "; } ChangeDescription += "signing"; } ChangeDescription += " key"; if (bCycleEncryptionKey && bCycleSigningKey) { ChangeDescription += "s"; } ChangeDescription += " for project " + Params.ShortProjectName; P4Connection SubmitP4 = null; int NewCL = 0; if (CommandUtils.P4Enabled) { SubmitP4 = CommandUtils.P4; NewCL = SubmitP4.CreateChange(Description: ChangeDescription); SubmitP4.Revert(String.Format("-k \"{0}\"", DestinationFile.FullName)); SubmitP4.Sync(String.Format("-k \"{0}\"", DestinationFile.FullName), AllowSpew: false); SubmitP4.Add(NewCL, String.Format("\"{0}\"", DestinationFile.FullName)); SubmitP4.Edit(NewCL, String.Format("\"{0}\"", DestinationFile.FullName)); } else { Log(ChangeDescription); FileReference.MakeWriteable(OutputFile); } string CommandletParams = ""; if (bCycleAllKeys) { CommandletParams = "-updateallkeys"; } else if (bCycleEncryptionKey) { CommandletParams = "-updateencryptionkey"; } else if (bCycleSigningKey) { CommandletParams = "-updatesigningkey"; } RunCommandlet(ProjectPath, UE4EditorExe, "CryptoKeys", CommandletParams); if (DestinationFile != OutputFile) { File.Delete(DestinationFile.FullName); FileReference.Move(OutputFile, DestinationFile); } if (SubmitP4 != null) { int ActualCL; SubmitP4.Submit(NewCL, out ActualCL); } }
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 Platform WindowsTargetPlatform = Platform.GetPlatform(UnrealTargetPlatform.Win64); // Figure out all the files for the archive string ZipFileName = Path.Combine(OutputFolder, "Archive.zip"); using (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)); WindowsTargetPlatform.StripSymbols(new FileReference(BuildProduct), new FileReference(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 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.ServerAndPort); 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> /// Detects the current changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CL not set, detecting 'have' CL..."); // Retrieve the current changelist var P4Result = Connection.P4("changes -m 1 " + CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath, "/...#have"), AllowSpew: false); var CLTokens = P4Result.Output.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var CLString = CLTokens[1]; var CL = Int32.Parse(CLString); if (CLString != CL.ToString()) { throw new AutomationException("Failed to retrieve current changelist."); } return CLString; }
internal P4Environment(P4Connection Connection, CommandEnvironment CmdEnv) { InitEnvironment(Connection, CmdEnv); }
void ExecuteInner(string Dir, int PR) { string PRNum = PR.ToString(); // Discard any old changes we may have committed RunGit("reset --hard"); // show-ref is just a double check that the PR exists //var Refs = RunGit("show-ref"); /*if (!Refs.Contains("refs/remotes/origin/pr/" + PRNum)) { throw new AutomationException("This is not among the refs: refs/remotes/origin/pr/{0}", PRNum); }*/ RunGit(String.Format("fetch origin refs/pull/{0}/head:pr/{1}", PRNum, PRNum)); RunGit(String.Format("checkout pr/{0} --", PRNum)); int CLBase; string DepotBase; ScanForBranchAndCL_BaseVersion(String.Format("log --author=TimSweeney --author=UnrealBot -100 pr/{0} --", PRNum), out DepotBase, out CLBase); int CLLive; string DepotLive; ScanForBranchAndCL_LiveVersion(String.Format("log -100 pr/{0} --", PRNum), out DepotLive, out CLLive); if (CLLive == 0 && CLBase == 0) { throw new AutomationException("Could not find a base change and branch using either method."); } int CL = 0; string Depot = ""; if (CLBase > CLLive) { CL = CLBase; Depot = DepotBase; } else { CL = CLLive; Depot = DepotLive; } if (CL < 2000000 || String.IsNullOrWhiteSpace(Depot)) { throw new AutomationException("Could not find a base change and branch using either method."); } P4ClientInfo NewClient = P4.GetClientInfo(P4Env.Client); foreach (var p in NewClient.View) { Log("{0} = {1}", p.Key, p.Value); } string TestClient = P4Env.User + "_" + Environment.MachineName + "_PullRequests_" + Depot.Replace("/", "_"); NewClient.Owner = P4Env.User; NewClient.Host = Environment.MachineName; NewClient.RootPath = Dir; NewClient.Name = TestClient; NewClient.View = new List<KeyValuePair<string, string>>(); NewClient.View.Add(new KeyValuePair<string, string>(Depot + "/...", "/...")); if (!P4.DoesClientExist(TestClient)) { P4.CreateClient(NewClient); } var P4Sub = new P4Connection(P4Env.User, TestClient, P4Env.P4Port); P4Sub.Sync(String.Format("-f -k -q {0}/...@{1}", Depot, CL)); var Change = P4Sub.CreateChange(null, String.Format("GitHub pull request #{0}", PRNum)); P4Sub.ReconcileNoDeletes(Change, CommandUtils.MakePathSafeToUseWithCommandLine(CombinePaths(Dir, bDoingUT ? "UnrealTournament" : "Engine", "..."))); P4Sub.Shelve(Change); P4Sub.Revert(Change, "-k //..."); }
/// <summary> /// Initializes default source control connection. /// </summary> static internal void InitDefaultP4Connection() { CheckP4Enabled(); PerforceConnection = new P4Connection(User: P4Env.User, Client: P4Env.Client, ServerAndPort: P4Env.P4Port); }
/// <summary> /// Constructor. Derives the Perforce environment settings. /// </summary> internal P4Environment(CommandEnvironment CmdEnv) { // Get the Perforce port setting ServerAndPort = CommandUtils.GetEnvVar(EnvVarNames.P4Port); if (String.IsNullOrEmpty(ServerAndPort)) { ServerAndPort = DetectP4Port(); CommandUtils.SetEnvVar(EnvVarNames.P4Port, ServerAndPort); } // Get the Perforce user setting User = CommandUtils.GetEnvVar(EnvVarNames.User); if (String.IsNullOrEmpty(User)) { P4Connection DefaultConnection = new P4Connection(User: null, Client: null, ServerAndPort: ServerAndPort); User = DetectUserName(DefaultConnection); CommandUtils.SetEnvVar(EnvVarNames.User, User); } // Get the Perforce client setting Client = CommandUtils.GetEnvVar(EnvVarNames.Client); if (String.IsNullOrEmpty(Client)) { P4Connection DefaultConnection = new P4Connection(User: User, Client: null, ServerAndPort: ServerAndPort); P4ClientInfo ThisClient = DetectClient(DefaultConnection, User, Environment.MachineName.ToLower(), CmdEnv.UATExe); Log.TraceInformation("Using user {0} clientspec {1} {2}", User, ThisClient.Name, ThisClient.RootPath); string BranchPath; string ClientRootPath; P4Connection ClientConnection = new P4Connection(User: User, Client: ThisClient.Name, ServerAndPort: ServerAndPort); DetectRootPaths(ClientConnection, CmdEnv.LocalRoot, ThisClient, out BranchPath, out ClientRootPath); Client = ThisClient.Name; CommandUtils.SetEnvVar(EnvVarNames.Client, Client); Branch = BranchPath; CommandUtils.SetEnvVar(EnvVarNames.BuildRootP4, Branch); ClientRoot = ClientRootPath; CommandUtils.SetEnvVar(EnvVarNames.ClientRoot, ClientRootPath); } else { Branch = CommandUtils.GetEnvVar(EnvVarNames.BuildRootP4); ClientRoot = CommandUtils.GetEnvVar(EnvVarNames.ClientRoot); if (String.IsNullOrEmpty(Branch) || String.IsNullOrEmpty(ClientRoot)) { throw new AutomationException("{0} and {1} must also be set with {2}", EnvVarNames.ClientRoot, EnvVarNames.BuildRootP4, EnvVarNames.Client); } } // We expect the build root to not end with a path separator if (Branch.EndsWith("/")) { Branch = Branch.TrimEnd('/'); CommandUtils.SetEnvVar(EnvVarNames.BuildRootP4, Branch); } // Set the current changelist string ChangelistString = CommandUtils.GetEnvVar(EnvVarNames.Changelist, null); if (String.IsNullOrEmpty(ChangelistString) && CommandUtils.P4CLRequired) { P4Connection Connection = new P4Connection(User, Client, ServerAndPort); ChangelistString = DetectCurrentCL(Connection, ClientRoot); CommandUtils.SetEnvVar(EnvVarNames.Changelist, ChangelistString); } if (!String.IsNullOrEmpty(ChangelistString)) { Changelist = int.Parse(ChangelistString); } // Set the current code changelist string CodeChangelistString = CommandUtils.GetEnvVar(EnvVarNames.CodeChangelist); if (String.IsNullOrEmpty(CodeChangelistString) && CommandUtils.P4CLRequired) { P4Connection Connection = new P4Connection(User, Client, ServerAndPort); CodeChangelistString = DetectCurrentCodeCL(Connection, ClientRoot); CommandUtils.SetEnvVar(EnvVarNames.CodeChangelist, CodeChangelistString); } if (!String.IsNullOrEmpty(CodeChangelistString)) { CodeChangelist = int.Parse(CodeChangelistString); } // Set the standard environment variables based on the values we've found CommandUtils.SetEnvVar("P4PORT", ServerAndPort); CommandUtils.SetEnvVar("P4USER", User); CommandUtils.SetEnvVar("P4CLIENT", Client); // Write a summary of the settings to the output window if (!CommandUtils.CmdEnv.IsChildInstance) { Log.TraceInformation("Detected Perforce Settings:"); Log.TraceInformation(" Server: {0}", ServerAndPort); Log.TraceInformation(" User: {0}", User); Log.TraceInformation(" Client: {0}", Client); Log.TraceInformation(" Branch: {0}", Branch); if (ChangelistInternal != -1) { Log.TraceInformation(" Last Change: {0}", Changelist); } if (CodeChangelistInternal != -1) { Log.TraceInformation(" Last Code Change: {0}", CodeChangelist); } } // Write all the environment variables to the log Log.TraceLog("Perforce Environment Variables:"); Log.TraceLog(" {0}={1}", EnvVarNames.P4Port, InternalUtils.GetEnvironmentVariable(EnvVarNames.P4Port, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.User, InternalUtils.GetEnvironmentVariable(EnvVarNames.User, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.Client, InternalUtils.GetEnvironmentVariable(EnvVarNames.Client, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.BuildRootP4, InternalUtils.GetEnvironmentVariable(EnvVarNames.BuildRootP4, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.BuildRootEscaped, InternalUtils.GetEnvironmentVariable(EnvVarNames.BuildRootEscaped, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.ClientRoot, InternalUtils.GetEnvironmentVariable(EnvVarNames.ClientRoot, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.Changelist, InternalUtils.GetEnvironmentVariable(EnvVarNames.Changelist, "", true)); Log.TraceLog(" {0}={1}", EnvVarNames.CodeChangelist, InternalUtils.GetEnvironmentVariable(EnvVarNames.CodeChangelist, "", true)); Log.TraceLog(" {0}={1}", "P4PORT", InternalUtils.GetEnvironmentVariable("P4PORT", "", true)); Log.TraceLog(" {0}={1}", "P4USER", InternalUtils.GetEnvironmentVariable("P4USER", "", true)); Log.TraceLog(" {0}={1}", "P4CLIENT", InternalUtils.GetEnvironmentVariable("P4CLIENT", "", true)); }
public override void ExecuteBuild() { string Paths = ParseParamValue("Paths", null); if (string.IsNullOrWhiteSpace(Paths)) { throw new AutomationException("-Paths must be defined! Usage: -Paths=Path1/...;Path2.txt"); } string Description = ParseParamValue("Description", null); if (string.IsNullOrWhiteSpace(Description)) { throw new AutomationException("-Description must be defined!"); } string FileType = ParseParamValue("FileType", null); if (!CommandUtils.AllowSubmit) { LogWarning("Submitting to Perforce is disabled by default. Run with the -submit argument to allow."); } else { // Get the connection that we're going to submit with P4Connection SubmitP4 = CommandUtils.P4; // Reconcile the path against the depot int NewCL = SubmitP4.CreateChange(Description: Description.Replace("\\n", "\n")); try { foreach (string Path in Paths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { SubmitP4.Sync(String.Format("-k \"{0}\"", Path), AllowSpew: false); SubmitP4.Reconcile(NewCL, Path); if (FileType != null) { SubmitP4.P4(String.Format("reopen -t \"{0}\" \"{1}\"", FileType, Path), AllowSpew: false); } } if (SubmitP4.TryDeleteEmptyChange(NewCL)) { CommandUtils.LogInformation("No files to submit; ignored."); return; } // Submit it int SubmittedCL; SubmitP4.Submit(NewCL, out SubmittedCL, true); if (SubmittedCL <= 0) { throw new AutomationException("Submit failed."); } CommandUtils.LogInformation("Submitted in changelist {0}", SubmittedCL); } catch (Exception Ex) { LogError("Failed to reconcile and submit files to P4, reason: {0}, reverting and deleting change.", Ex.ToString()); SubmitP4.DeleteChange(NewCL); } } }
/// <summary> /// Detects a workspace given the current user name, host name and depot path. /// </summary> /// <param name="UserName">User name</param> /// <param name="HostName">Host</param> /// <param name="UATLocation">Path to UAT exe, this will be checked agains the root path.</param> /// <returns>Client to use.</returns> private static P4ClientInfo DetectClient(P4Connection Connection, string UserName, string HostName, string UATLocation) { CommandUtils.LogVerbose("uebp_CLIENT not set, detecting current client..."); var MatchingClients = new List<P4ClientInfo>(); P4ClientInfo[] P4Clients = Connection.GetClientsForUser(UserName, UATLocation); foreach (var Client in P4Clients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) != 0) { Log.TraceInformation("Rejecting client because of different Host {0} \"{1}\" != \"{2}\"", Client.Name, Client.Host, HostName); continue; } MatchingClients.Add(Client); } P4ClientInfo ClientToUse = null; if (MatchingClients.Count == 0) { throw new AutomationException("No matching clientspecs found!"); } else if (MatchingClients.Count == 1) { ClientToUse = MatchingClients[0]; } else { // We may have empty host clients here, so pick the first non-empty one if possible foreach (var Client in MatchingClients) { if (!String.IsNullOrEmpty(Client.Host) && String.Compare(Client.Host, HostName, true) == 0) { ClientToUse = Client; break; } } if (ClientToUse == null) { Log.TraceWarning("{0} clients found that match the current host and root path. The most recently accessed client will be used.", MatchingClients.Count); ClientToUse = GetMostRecentClient(MatchingClients); } } return ClientToUse; }
/// <summary> /// Detects the current code changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCodeCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CodeCL not set, detecting last code CL..."); // Retrieve the current changelist string P4Cmd = String.Format("changes -m 1 \"{0}/....cpp#have\" \"{0}/....h#have\" \"{0}/....inl#have\" \"{0}/....cs#have\" \"{0}/....usf#have\"", CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath)); IProcessResult P4Result = Connection.P4(P4Cmd, AllowSpew: false); // Loop through all the lines of the output. Even though we requested one result, we'll get one for each search pattern. int CL = 0; foreach(string Line in P4Result.Output.Split('\n')) { string[] Tokens = Line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if(Tokens.Length >= 2) { int LineCL = Int32.Parse(Tokens[1]); CL = Math.Max(CL, LineCL); } } return CL.ToString(); }
/// <summary> /// Initializes the environment. Tries to autodetect all source control settings. /// </summary> /// <param name="CompilationEnv">Compilation environment</param> protected override void InitEnvironment(P4Connection Connection, CommandEnvironment CmdEnv) { var HostName = Environment.MachineName.ToLower(); var P4PortEnv = DetectP4Port(); var UserName = CommandUtils.GetEnvVar(EnvVarNames.User); if (String.IsNullOrEmpty(UserName)) { UserName = DetectUserName(Connection); } var CommandLineClient = CommandUtils.GetEnvVar(EnvVarNames.Client); P4ClientInfo ThisClient = null; if (String.IsNullOrEmpty(CommandLineClient) == false) { ThisClient = Connection.GetClientInfo(CommandLineClient); if (ThisClient == null) { throw new AutomationException("Unable to find client {0}", CommandLineClient); } if (String.Compare(ThisClient.Owner, UserName, true) != 0) { throw new AutomationException("Client specified with {0}={1} has a different owner then the detected user name (has: {2}, expected: {3})", EnvVarNames.Client, CommandLineClient, ThisClient.Owner, UserName); } } else { ThisClient = DetectClient(Connection, UserName, HostName, CmdEnv.UATExe); } Log.TraceInformation("Using user {0} clientspec {1} {2}", UserName, ThisClient.Name, ThisClient.RootPath); Environment.SetEnvironmentVariable("P4CLIENT", ThisClient.Name); string BuildRootPath; string ClientRootPath; DetectRootPaths(Connection, CmdEnv.LocalRoot, ThisClient, out BuildRootPath, out ClientRootPath); CommandUtils.ConditionallySetEnvVar(EnvVarNames.P4Port, P4PortEnv); CommandUtils.ConditionallySetEnvVar(EnvVarNames.User, UserName); CommandUtils.ConditionallySetEnvVar(EnvVarNames.Client, ThisClient.Name); CommandUtils.ConditionallySetEnvVar(EnvVarNames.BuildRootP4, BuildRootPath); CommandUtils.ConditionallySetEnvVar(EnvVarNames.ClientRoot, ClientRootPath); var CLString = CommandUtils.GetEnvVar(EnvVarNames.Changelist, null); if (String.IsNullOrEmpty(CLString) && CommandUtils.P4CLRequired) { CLString = DetectCurrentCL(Connection, ClientRootPath); } if (!String.IsNullOrEmpty(CLString)) { CommandUtils.ConditionallySetEnvVar(EnvVarNames.Changelist, CLString); } var CodeCLString = CommandUtils.GetEnvVar(EnvVarNames.CodeChangelist, null); if (String.IsNullOrEmpty(CodeCLString) && CommandUtils.P4CLRequired) { CodeCLString = DetectCurrentCodeCL(Connection, ClientRootPath); } if (!String.IsNullOrEmpty(CodeCLString)) { CommandUtils.ConditionallySetEnvVar(EnvVarNames.CodeChangelist, CodeCLString); } CommandUtils.ConditionallySetEnvVar(EnvVarNames.LabelToSync, ""); CommandUtils.ConditionallySetEnvVar("P4USER", UserName); CommandUtils.ConditionallySetEnvVar("P4CLIENT", ThisClient.Name); var P4Password = Environment.GetEnvironmentVariable(EnvVarNames.P4Password); if (!String.IsNullOrEmpty(P4Password)) { CommandUtils.ConditionallySetEnvVar("P4PASSWD", P4Password); } SetBuildRootEscaped(); base.InitEnvironment(Connection, CmdEnv); }