PageRenderTime 27ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Malevich/SourceControl/Perforce.cs

#
C# | 241 lines | 159 code | 24 blank | 58 comment | 37 complexity | 9e41333ba7516872423b0ec83b4d24e6 MD5 | raw file
  1. //-----------------------------------------------------------------------
  2. // <copyright>
  3. // Copyright (C) Sergey Solyanik for The Malevich Project.
  4. //
  5. // This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
  6. // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
  7. // </copyright>
  8. //-----------------------------------------------------------------------
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.IO;
  13. using System.Text;
  14. using System.Text.RegularExpressions;
  15. using Microsoft.Win32;
  16. namespace SourceControl
  17. {
  18. /// <summary>
  19. /// The implementation of the perforce class.
  20. /// </summary>
  21. public sealed class Perforce : ISourceControlSystem
  22. {
  23. /// <summary>
  24. /// The endpoint of the perforce server (servername:tcpport).
  25. /// The name (Port) is a bit misleading, but it is in keeping with the perforce terminology.
  26. /// </summary>
  27. public string Port;
  28. /// <summary>
  29. /// The client string.
  30. /// </summary>
  31. public string Client;
  32. /// <summary>
  33. /// Perforce user name. Can be null.
  34. /// </summary>
  35. public string User;
  36. /// <summary>
  37. /// Perforce password. Can be null.
  38. /// </summary>
  39. public string Passwd;
  40. SourceControlType ISourceControlSystem.ServerType
  41. { get { return SourceControlType.PERFORCE; } }
  42. /// <summary>
  43. /// Trivial constructor.
  44. /// </summary>
  45. /// <param name="port"> The endpoint of the source perforce server (servername:tcpport). </param>
  46. /// <param name="client"> The name of the client. </param>
  47. /// <param name="user"> Perforce user name, can be null. </param>
  48. /// <param name="passwd"> Perforce password, can be null. </param>
  49. public Perforce(string port, string client, string user, string passwd)
  50. {
  51. Port = port;
  52. Client = client;
  53. User = user;
  54. Passwd = passwd;
  55. }
  56. }
  57. /// <summary>
  58. /// The wrapper for perforce version of PerforceBase source control interface.
  59. /// </summary>
  60. public sealed class PerforceInterface : PerforceBase
  61. {
  62. /// <summary>
  63. /// Verifies that perforce installation can actually be used. Throws SourceControlRuntimeError if it cannot be.
  64. /// </summary>
  65. private static void VerifyPerforceRequirements()
  66. {
  67. RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Perforce\Environment");
  68. if (key == null)
  69. return;
  70. try
  71. {
  72. if (key.GetValue("P4DIFF") != null)
  73. {
  74. Console.WriteLine();
  75. Console.WriteLine("P4DIFF variable is set in the registry.");
  76. Console.WriteLine("Review submission tool relies on default P4 differ");
  77. Console.WriteLine("will not work correctly with any other tool.");
  78. Console.WriteLine();
  79. Console.WriteLine("Consider moving P4DIFF configuration to p4config");
  80. Console.WriteLine("file or your environment, and remove its definition");
  81. Console.WriteLine("from the registry by running:");
  82. Console.WriteLine(" p4 set P4DIFF=");
  83. throw new SourceControlRuntimeError();
  84. }
  85. }
  86. finally
  87. {
  88. key.Close();
  89. }
  90. }
  91. /// <summary>
  92. /// Trivial constructor. Just wraps around the Perforce base.
  93. /// </summary>
  94. /// <param name="p4Client"> The location of p4 command. </param>
  95. /// <param name="port"> The port of perforce: servername:tcpport form. </param>
  96. /// <param name="client"> The client name. See sd.ini. </param>
  97. /// <param name="user"> Perforce user name, can be null. </param>
  98. /// <param name="passwd"> Perforce password, can be null. </param>
  99. private PerforceInterface(string p4Client, string port, string client, string user, string passwd)
  100. : base(p4Client, new Perforce(port, client, user, passwd))
  101. {
  102. }
  103. /// <summary>
  104. /// Factory for the perforce connector instances.
  105. /// </summary>
  106. /// <param name="p4Client"> The location of p4 command. </param>
  107. /// <param name="port"> The port of perforce: servername:tcpport form. </param>
  108. /// <param name="client"> The client name. See sd.ini. </param>
  109. /// <param name="user"> Perforce user name, can be null. </param>
  110. /// <param name="passwd"> Perforce password, can be null. </param>
  111. /// <returns> The source control instance. </returns>
  112. public static ISourceControl GetInstance(string p4Client, string port, string client,
  113. string user, string passwd)
  114. {
  115. VerifyPerforceRequirements();
  116. return new PerforceInterface(p4Client, port, client, user, passwd);
  117. }
  118. /// <summary>
  119. /// Gets the perforce client settings.
  120. /// </summary>
  121. /// <returns></returns>
  122. public static SourceControlSettings GetSettings()
  123. {
  124. SourceControlSettings settings = new SourceControlSettings();
  125. settings.Port = Environment.GetEnvironmentVariable("P4PORT");
  126. if (settings.Port != null)
  127. settings.Port = settings.Port.Trim();
  128. settings.Client = Environment.GetEnvironmentVariable("P4CLIENT");
  129. if (settings.Client != null)
  130. settings.Client = settings.Client.Trim();
  131. settings.User = Environment.GetEnvironmentVariable("P4USER");
  132. if (settings.User != null)
  133. settings.User = settings.User.Trim();
  134. settings.Password = Environment.GetEnvironmentVariable("P4PASSWD");
  135. string path = Environment.GetEnvironmentVariable("path").Replace("\"", "");
  136. string[] pathArray = path.Split(';');
  137. for (int i = 0; i < pathArray.Length; ++i)
  138. {
  139. string p4 = Path.Combine(pathArray[i], "p4.exe");
  140. if (File.Exists(p4))
  141. {
  142. settings.ClientExe = p4;
  143. break;
  144. }
  145. }
  146. string p4Config = Environment.GetEnvironmentVariable("P4CONFIG");
  147. if (p4Config != null)
  148. {
  149. string dir = Directory.GetCurrentDirectory();
  150. string root = Path.GetPathRoot(dir);
  151. while (!dir.Equals(root))
  152. {
  153. string p4 = Path.Combine(dir, p4Config);
  154. if (File.Exists(p4))
  155. {
  156. Regex portRegex = new Regex(@"^(\s)*P4PORT(\s)*=(\s)*(?<port>(\S)*)(\s)*$",
  157. RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
  158. Regex clientRegex = new Regex(@"^(\s)*P4CLIENT(\s)*=(\s)*(?<client>(\S)*)(\s)*$",
  159. RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
  160. Regex userRegex = new Regex(@"^(\s)*P4USER(\s)*=(\s)*(?<user>(\S)*)(\s)*$",
  161. RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
  162. Regex passwdRegex = new Regex(@"^(\s)*P4PASSWD(\s)*=(\s)*(?<passwd>(\S)*)(\s)*$",
  163. RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
  164. StreamReader sr = new StreamReader(p4);
  165. while (settings.Port == null || settings.Client == null || settings.User == null ||
  166. settings.Password == null)
  167. {
  168. string l = sr.ReadLine();
  169. if (l == null)
  170. break;
  171. if (settings.Port == null)
  172. {
  173. Match portMatch = portRegex.Match(l);
  174. if (portMatch.Success)
  175. {
  176. settings.Port = portMatch.Groups[1].Value;
  177. continue;
  178. }
  179. }
  180. if (settings.Client == null)
  181. {
  182. Match clientMatch = clientRegex.Match(l);
  183. if (clientMatch.Success)
  184. {
  185. settings.Client = clientMatch.Groups[1].Value;
  186. continue;
  187. }
  188. }
  189. if (settings.User == null)
  190. {
  191. Match userMatch = userRegex.Match(l);
  192. if (userMatch.Success)
  193. {
  194. settings.User = userMatch.Groups[1].Value;
  195. continue;
  196. }
  197. }
  198. if (settings.Password == null)
  199. {
  200. Match passwdMatch = passwdRegex.Match(l);
  201. if (passwdMatch.Success)
  202. {
  203. settings.Password = passwdMatch.Groups[1].Value;
  204. continue;
  205. }
  206. }
  207. }
  208. sr.Close();
  209. break;
  210. }
  211. dir = Path.GetDirectoryName(dir);
  212. }
  213. }
  214. return settings;
  215. }
  216. }
  217. }