示例#1
0
		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);
		}
示例#2
0
		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);
			}
		}
		}
示例#4
0
 /// <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;
 }
示例#5
0
 /// <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);
				}
			}
		}
示例#7
0
        /// <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;
        }