public static void GetDefaultServerSettings(ref string ServerAndPort, ref string UserName, TextWriter Log) { // Read the P4PORT setting for the server, if necessary. Change to the project folder if set, so we can respect the contents of any P4CONFIG file. if (ServerAndPort == null) { PerforceConnection Perforce = new PerforceConnection(UserName, null, null); string NewServerAndPort; if (Perforce.GetSetting("P4PORT", out NewServerAndPort, Log)) { ServerAndPort = NewServerAndPort; } else { ServerAndPort = PerforceConnection.DefaultServerAndPort; } } // Update the server and username from the reported server info if it's not set if (UserName == null) { PerforceConnection Perforce = new PerforceConnection(UserName, null, ServerAndPort); PerforceInfoRecord PerforceInfo; if (Perforce.Info(out PerforceInfo, Log) && !String.IsNullOrEmpty(PerforceInfo.UserName)) { UserName = PerforceInfo.UserName; } else { UserName = Environment.UserName; } } }
public static bool TryGetServerSettings(string ProjectFileName, ref string ServerAndPort, ref string UserName, TextWriter Log) { // Read the P4PORT setting for the server, if necessary. Change to the project folder if set, so we can respect the contents of any P4CONFIG file. if (ServerAndPort == null) { string PrevDirectory = Directory.GetCurrentDirectory(); try { PerforceConnection Perforce = new PerforceConnection(UserName, null, null); if (ProjectFileName != null) { try { Directory.SetCurrentDirectory(Path.GetDirectoryName(ProjectFileName)); } catch { // Just ignore } } string NewServerAndPort; if (Perforce.GetSetting("P4PORT", out NewServerAndPort, Log)) { ServerAndPort = NewServerAndPort; } } finally { Directory.SetCurrentDirectory(PrevDirectory); } } // Update the server and username from the reported server info if it's not set if (ServerAndPort == null || UserName == null) { PerforceConnection Perforce = new PerforceConnection(UserName, null, ServerAndPort); PerforceInfoRecord PerforceInfo; if (!Perforce.Info(out PerforceInfo, Log)) { return(false); } if (ServerAndPort == null && !String.IsNullOrEmpty(PerforceInfo.ServerAddress)) { ServerAndPort = PerforceInfo.ServerAddress; } if (UserName == null && !String.IsNullOrEmpty(PerforceInfo.UserName)) { UserName = PerforceInfo.UserName; } if (ServerAndPort == null || UserName == null) { return(false); } } // Otherwise succeed return(true); }
public bool Run(out string ErrorMessage) { Log.WriteLine("Finding files in workspace..."); Log.WriteLine(); // Start enumerating all the files that exist locally foreach (string SyncPath in SyncPaths) { Debug.Assert(SyncPath.StartsWith(ClientRootPath)); if (SyncPath.StartsWith(ClientRootPath, StringComparison.InvariantCultureIgnoreCase)) { string[] Fragments = SyncPath.Substring(ClientRootPath.Length).Split('/'); FolderToClean SyncFolder = RootFolderToClean; for (int Idx = 0; Idx < Fragments.Length - 1; Idx++) { FolderToClean NextSyncFolder; if (!SyncFolder.NameToSubFolder.TryGetValue(Fragments[Idx], out NextSyncFolder)) { NextSyncFolder = new FolderToClean(new DirectoryInfo(Path.Combine(SyncFolder.Directory.FullName, Fragments[Idx]))); SyncFolder.NameToSubFolder[NextSyncFolder.Name] = NextSyncFolder; } SyncFolder = NextSyncFolder; } string Wildcard = Fragments[Fragments.Length - 1]; if (Wildcard == "...") { QueueFolderToPopulate(SyncFolder); } else { if (SyncFolder.Directory.Exists) { foreach (FileInfo File in SyncFolder.Directory.EnumerateFiles(Wildcard)) { SyncFolder.NameToFile[File.Name] = File; } } } } } // Get the prefix for any local file string LocalRootPrefix = RootFolderToClean.Directory.FullName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; // Query the have table and build a separate tree from it PerforceHaveFolder RootHaveFolder = new PerforceHaveFolder(); foreach (string SyncPath in SyncPaths) { List <PerforceFileRecord> FileRecords; if (!PerforceClient.Stat(String.Format("{0}#have", SyncPath), out FileRecords, Log)) { ErrorMessage = "Couldn't query have table from Perforce."; return(false); } foreach (PerforceFileRecord FileRecord in FileRecords) { if (!FileRecord.ClientPath.StartsWith(LocalRootPrefix, StringComparison.InvariantCultureIgnoreCase)) { ErrorMessage = String.Format("Failed to get have table; file '{0}' doesn't start with root path ('{1}')", FileRecord.ClientPath, RootFolderToClean.Directory.FullName); return(false); } string[] Tokens = FileRecord.ClientPath.Substring(LocalRootPrefix.Length).Split('/', '\\'); PerforceHaveFolder FileFolder = RootHaveFolder; for (int Idx = 0; Idx < Tokens.Length - 1; Idx++) { PerforceHaveFolder NextFileFolder; if (!FileFolder.NameToSubFolder.TryGetValue(Tokens[Idx], out NextFileFolder)) { NextFileFolder = new PerforceHaveFolder(); FileFolder.NameToSubFolder.Add(Tokens[Idx], NextFileFolder); } FileFolder = NextFileFolder; } FileFolder.NameToFile[Tokens[Tokens.Length - 1]] = FileRecord; } } // Find all the files which are currently open for edit. We don't want to force sync these. List <PerforceFileRecord> OpenFileRecords; if (!PerforceClient.GetOpenFiles("//...", out OpenFileRecords, Log)) { ErrorMessage = "Couldn't query open files from Perforce."; return(false); } // Build a set of all the open local files HashSet <string> OpenLocalFiles = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (PerforceFileRecord OpenFileRecord in OpenFileRecords) { if (!OpenFileRecord.ClientPath.StartsWith(ClientRootPath, StringComparison.InvariantCultureIgnoreCase)) { ErrorMessage = String.Format("Failed to get open file list; file '{0}' doesn't start with client root path ('{1}')", OpenFileRecord.ClientPath, ClientRootPath); return(false); } OpenLocalFiles.Add(LocalRootPrefix + PerforceUtils.UnescapePath(OpenFileRecord.ClientPath).Substring(ClientRootPath.Length).Replace('/', Path.DirectorySeparatorChar)); } // Wait to finish scanning the directory FinishedScan.WaitOne(); // Find the value of the P4CONFIG variable string PerforceConfigFile; PerforceClient.GetSetting("P4CONFIG", out PerforceConfigFile, Log); // Merge the trees MergeTrees(RootFolderToClean, RootHaveFolder, OpenLocalFiles, PerforceConfigFile); // Remove all the empty folders RemoveEmptyFolders(RootFolderToClean); ErrorMessage = null; return(true); }
public bool Run(out string ErrorMessage) { PerforceConnection Perforce = new PerforceConnection(null, null, null); // Get the P4PORT setting in this folder, so we can respect the contents of any P4CONFIG file string PrevDirectory = Directory.GetCurrentDirectory(); try { Directory.SetCurrentDirectory(Path.GetDirectoryName(NewSelectedFileName)); string ServerAndPort; if (Perforce.GetSetting("P4PORT", out ServerAndPort, Log)) { Perforce = new PerforceConnection(null, null, ServerAndPort); } } finally { Directory.SetCurrentDirectory(PrevDirectory); } // Get the Perforce server info PerforceInfoRecord PerforceInfo; if (!Perforce.Info(out PerforceInfo, Log)) { ErrorMessage = String.Format("Couldn't get Perforce server info"); return(false); } if (String.IsNullOrEmpty(PerforceInfo.UserName)) { ErrorMessage = "Missing user name in call to p4 info"; return(false); } if (String.IsNullOrEmpty(PerforceInfo.HostName)) { ErrorMessage = "Missing host name in call to p4 info"; return(false); } ServerTimeZone = PerforceInfo.ServerTimeZone; // Find all the clients on this machine Log.WriteLine("Enumerating clients on local machine..."); List <PerforceClientRecord> Clients; if (!Perforce.FindClients(out Clients, Log)) { ErrorMessage = String.Format("Couldn't find any clients for this host."); return(false); } // Find any clients which are valid. If this is not exactly one, we should fail. List <PerforceConnection> CandidateClients = new List <PerforceConnection>(); foreach (PerforceClientRecord Client in Clients) { // Make sure the client is well formed if (!String.IsNullOrEmpty(Client.Name) && (!String.IsNullOrEmpty(Client.Host) || !String.IsNullOrEmpty(Client.Owner)) && !String.IsNullOrEmpty(Client.Root)) { // Require either a username or host name match if ((String.IsNullOrEmpty(Client.Host) || String.Compare(Client.Host, PerforceInfo.HostName, StringComparison.InvariantCultureIgnoreCase) == 0) && (String.IsNullOrEmpty(Client.Owner) || String.Compare(Client.Owner, PerforceInfo.UserName, StringComparison.InvariantCultureIgnoreCase) == 0)) { if (!Utility.SafeIsFileUnderDirectory(NewSelectedFileName, Client.Root)) { Log.WriteLine("Rejecting {0} due to root mismatch ({1})", Client.Name, Client.Root); continue; } PerforceConnection CandidateClient = new PerforceConnection(PerforceInfo.UserName, Client.Name, Perforce.ServerAndPort); bool bFileExists; if (!CandidateClient.FileExists(NewSelectedFileName, out bFileExists, Log) || !bFileExists) { Log.WriteLine("Rejecting {0} due to file not existing in workspace", Client.Name); continue; } List <PerforceFileRecord> Records; if (!CandidateClient.Stat(NewSelectedFileName, out Records, Log)) { Log.WriteLine("Rejecting {0} due to {1} not in depot", Client.Name, NewSelectedFileName); continue; } Records.RemoveAll(x => !x.IsMapped); if (Records.Count == 0) { Log.WriteLine("Rejecting {0} due to {1} matching records", Client.Name, Records.Count); continue; } Log.WriteLine("Found valid client {0}", Client.Name); CandidateClients.Add(CandidateClient); } } } // Check there's only one client if (CandidateClients.Count == 0) { ErrorMessage = String.Format("Couldn't find any Perforce workspace containing {0}.", NewSelectedFileName); return(false); } else if (CandidateClients.Count > 1) { ErrorMessage = String.Format("Found multiple workspaces containing {0}:\n\n{1}\n\nCannot determine which to use.", Path.GetFileName(NewSelectedFileName), String.Join("\n", CandidateClients.Select(x => x.ClientName))); return(false); } // Take the client we've chosen PerforceClient = CandidateClients[0]; // Get the client path for the project file if (!PerforceClient.ConvertToClientPath(NewSelectedFileName, out NewSelectedClientFileName, Log)) { ErrorMessage = String.Format("Couldn't get client path for {0}", NewSelectedFileName); return(false); } // Figure out where the engine is in relation to it for (int EndIdx = NewSelectedClientFileName.Length - 1;; EndIdx--) { if (EndIdx < 2) { ErrorMessage = String.Format("Could not find engine in Perforce relative to project path ({0})", NewSelectedClientFileName); return(false); } if (NewSelectedClientFileName[EndIdx] == '/') { bool bFileExists; if (PerforceClient.FileExists(NewSelectedClientFileName.Substring(0, EndIdx) + "/Engine/Source/UE4Editor.target.cs", out bFileExists, Log) && bFileExists) { BranchClientPath = NewSelectedClientFileName.Substring(0, EndIdx); break; } } } Log.WriteLine("Found branch root at {0}", BranchClientPath); // Get the local branch root if (!PerforceClient.ConvertToLocalPath(BranchClientPath + "/Engine/Source/UE4Editor.target.cs", out BaseEditorTargetPath, Log)) { ErrorMessage = String.Format("Couldn't get local path for editor target file"); return(false); } // Find the editor target for this project if (NewSelectedFileName.EndsWith(".uproject", StringComparison.InvariantCultureIgnoreCase)) { List <PerforceFileRecord> Files; if (PerforceClient.FindFiles(PerforceUtils.GetClientOrDepotDirectoryName(NewSelectedClientFileName) + "/Source/*Editor.Target.cs", out Files, Log) && Files.Count >= 1) { PerforceFileRecord File = Files.FirstOrDefault(x => x.Action == null || !x.Action.Contains("delete")); if (File == null) { Log.WriteLine("Couldn't find any non-deleted editor targets for this project."); } else { string DepotPath = File.DepotPath; NewProjectEditorTarget = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(DepotPath.Substring(DepotPath.LastIndexOf('/') + 1))); Log.WriteLine("Using {0} as editor target name (from {1})", NewProjectEditorTarget, Files[0]); } } else { Log.WriteLine("Couldn't find any editor targets for this project."); } } // Get a unique name for the project that's selected. For regular branches, this can be the depot path. For streams, we want to include the stream name to encode imports. if (PerforceClient.GetActiveStream(out StreamName, Log)) { string ExpectedPrefix = String.Format("//{0}/", PerforceClient.ClientName); if (!NewSelectedClientFileName.StartsWith(ExpectedPrefix, StringComparison.InvariantCultureIgnoreCase)) { ErrorMessage = String.Format("Unexpected client path; expected '{0}' to begin with '{1}'", NewSelectedClientFileName, ExpectedPrefix); return(false); } string StreamPrefix; if (!TryGetStreamPrefix(PerforceClient, StreamName, Log, out StreamPrefix)) { ErrorMessage = String.Format("Failed to get stream info for {0}", StreamName); return(false); } NewSelectedProjectIdentifier = String.Format("{0}/{1}", StreamPrefix, NewSelectedClientFileName.Substring(ExpectedPrefix.Length)); } else { if (!PerforceClient.ConvertToDepotPath(NewSelectedClientFileName, out NewSelectedProjectIdentifier, Log)) { ErrorMessage = String.Format("Couldn't get depot path for {0}", NewSelectedFileName); return(false); } } // Read the project logo if (NewSelectedFileName.EndsWith(".uproject", StringComparison.InvariantCultureIgnoreCase)) { string LogoFileName = Path.Combine(Path.GetDirectoryName(NewSelectedFileName), "Build", "UnrealGameSync.png"); if (File.Exists(LogoFileName)) { try { // Duplicate the image, otherwise we'll leave the file locked using (Image Image = Image.FromFile(LogoFileName)) { ProjectLogo = new Bitmap(Image); } } catch { ProjectLogo = null; } } } // Succeeed! ErrorMessage = null; return(true); }