AcUtils
A high performance abstraction layer for AccuRev
AcQuery.cs
Go to the documentation of this file.
1 
16 using System;
17 using System.Collections.Generic;
18 using System.Configuration;
19 using System.Diagnostics;
20 using System.Globalization;
21 using System.IO;
22 using System.Linq;
23 using System.Threading.Tasks;
24 using System.Xml.Linq;
25 
26 namespace AcUtils
27 {
31  [Serializable]
32  public static class AcQuery
33  {
39 
43 
49  public static async Task<string> getPrincipalAsync()
50  {
51  string prncpl = null;
52  try
53  {
54  AcResult r = await AcCommand.runAsync("info").ConfigureAwait(false);
55  if (r != null && r.RetVal == 0)
56  {
57  using (StringReader reader = new StringReader(r.CmdResult))
58  {
59  bool? login = null; // don't know yet
60  string line;
61  char[] sep = new char[] { ':' };
62  while ((line = reader.ReadLine()) != null && login == null)
63  {
64  string[] arr = line.Split(sep); // "Principal: barnyrd"
65  if (arr.Length == 2)
66  {
67  if (String.Equals(arr[0], "Principal"))
68  {
69  string temp = arr[1].Replace("\t", "");
70  if (String.Equals(temp, "(not logged in)"))
71  login = false;
72  else
73  {
74  prncpl = temp; // AccuRev principal name
75  login = true;
76  }
77  }
78  }
79  }
80  }
81  }
82  }
83 
84  catch (AcUtilsException ecx)
85  {
86  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getPrincipalAsync{Environment.NewLine}{ecx.Message}");
87  }
88 
89  catch (Exception ecx)
90  {
91  AcDebug.Log($"Exception caught and logged in AcQuery.getPrincipalAsync{Environment.NewLine}{ecx.Message}");
92  }
93 
94  return prncpl; // principal name or null if not logged in
95  }
96 
109 
110 
119  public static async Task<string> getCatFileAsync(int eid, AcDepot depot, string ver_spec)
120  {
121  string tmpFile = null;
122  try
123  {
124  AcResult r = await AcCommand.runAsync($@"cat -v ""{ver_spec}"" -p ""{depot}"" -e {eid}")
125  .ConfigureAwait(false);
126  if (r != null && r.RetVal == 0)
127  {
128  tmpFile = Path.GetTempFileName();
129  using (StreamWriter streamWriter = new StreamWriter(tmpFile))
130  {
131  streamWriter.Write(r.CmdResult);
132  }
133  }
134  }
135 
136  catch (AcUtilsException ecx)
137  {
138  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getCatFileAsync{Environment.NewLine}{ecx.Message}");
139  }
140 
141  catch (Exception ecx) // IOException, DirectoryNotFoundException, PathTooLongException, SecurityException... others
142  {
143  AcDebug.Log($"Exception caught and logged in AcQuery.getCatFileAsync{Environment.NewLine}{ecx.Message}");
144  }
145 
146  return tmpFile;
147  }
148 
159 
164  public static async Task<int[]> getBackedVersionAsync(string realverspec, AcDepot depot, string depotrelpath)
168  {
169  int[] arr = null; // {realStreamNumber, realVersionNumber}
170  try
171  {
172  AcResult r = await AcCommand.runAsync($@"diff -fx -v ""{realverspec}"" -b -i -p ""{depot}"" ""{depotrelpath}""")
173  .ConfigureAwait(false);
174  if (r != null && r.RetVal < 2)
175  {
176  XElement xml = XElement.Parse(r.CmdResult);
177  XElement stream2 = xml.Descendants().Where(n => n.Name == "Stream2").SingleOrDefault();
178  if (stream2 != null)
179  {
180  XAttribute version = stream2.Attributes("Version").SingleOrDefault();
181  if (version != null)
182  {
183  string temp = (string)version;
184  string[] a = temp.Split('/');
185  int realStreamNumber = Int32.Parse(a[0], NumberStyles.Integer);
186  int realVersionNumber = Int32.Parse(a[1], NumberStyles.Integer);
187  arr = new int[] { realStreamNumber, realVersionNumber };
188  }
189  }
190  }
191  }
192 
193  catch (AcUtilsException ecx)
194  {
195  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getBackedVersionAsync{Environment.NewLine}{ecx.Message}");
196  }
197 
198  catch (Exception ecx)
199  {
200  AcDebug.Log($"Exception caught and logged in AcQuery.getBackedVersionAsync{Environment.NewLine}{ecx.Message}");
201  }
202 
203  return arr;
204  }
205 
213 
214 
233  public static async Task<Tuple<string, int>> getElementNameAsync(string stream, int EID)
234  {
235  Tuple<string, int> ret = null; // depot-relative path, parent folder EID
236  try
237  {
238  AcResult r = await AcCommand.runAsync($@"name -v ""{stream}"" -fx -e {EID}").ConfigureAwait(false);
239  if (r != null && r.RetVal == 0)
240  {
241  XElement xml = XElement.Parse(r.CmdResult);
242  string location = (string)xml.Element("element").Attribute("location");
243  int parent_id = (int)xml.Element("element").Attribute("parent_id");
244  ret = Tuple.Create(location, parent_id);
245  }
246  }
247 
248  catch (AcUtilsException ecx)
249  {
250  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getElementNameAsync{Environment.NewLine}{ecx.Message}");
251  }
252 
253  catch (Exception ecx)
254  {
255  AcDebug.Log($"Exception caught and logged in AcQuery.getElementNameAsync{Environment.NewLine}{ecx.Message}");
256  }
257 
258  return ret;
259  }
260 
267 
268  public static T getAppConfigSetting<T>(string key)
269  {
270  var value = ConfigurationManager.AppSettings[key];
271  return (T)System.Convert.ChangeType(value, typeof(T),
272  CultureInfo.InvariantCulture);
273  }
274 
279 
280 
293  public static async Task<int[]> getAccuRevVersionAsync()
294  {
295  int[] arr = null; // major, minor, patch
296  string tempFile = null;
297  try
298  {
299  tempFile = Path.GetTempFileName(); // the AccuRev xml command requires a file as its argument
300  using (StreamWriter streamWriter = new StreamWriter(tempFile))
301  {
302  streamWriter.Write(@"<serverInfo/>"); // set up the query
303  }
304 
305  AcResult r = await AcCommand.runAsync($@"xml -l ""{tempFile}""").ConfigureAwait(false);
306  if (r != null && r.RetVal == 0)
307  {
308  using (StringReader reader = new StringReader(r.CmdResult))
309  {
310  XElement doc = XElement.Load(reader);
311  XElement sv = doc.Element("serverVersion");
312  int major = (int)sv.Attribute("major");
313  int minor = (int)sv.Attribute("minor");
314  int patch = (int)sv.Attribute("patch");
315  arr = new int[] { major, minor, patch };
316  }
317  }
318  }
319 
320  catch (AcUtilsException ecx)
321  {
322  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getAccuRevVersionAsync{Environment.NewLine}{ecx.Message}");
323  }
324 
325  catch (Exception ecx)
326  {
327  AcDebug.Log($"Exception caught and logged in AcQuery.getAccuRevVersionAsync{Environment.NewLine}{ecx.Message}");
328  }
329 
330  finally
331  {
332  if (tempFile != null)
333  File.Delete(tempFile);
334  }
335 
336  return arr;
337  }
338 
344 
345  public static async Task<int> getUsersCountAsync(bool includeDeactivated = false)
349  {
350  int count = -1; // assume failure
351  try
352  {
353  AcResult r = await AcCommand.runAsync(includeDeactivated ? "show -fix users" : "show -fx users").ConfigureAwait(false);
354  if (r != null && r.RetVal == 0)
355  {
356  XElement t = XElement.Parse(r.CmdResult);
357  count = t.Elements("Element").Count();
358  }
359  }
360 
361  catch (AcUtilsException ecx)
362  {
363  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getUsersCountAsync{Environment.NewLine}{ecx.Message}");
364  }
365 
366  catch (Exception ecx)
367  {
368  AcDebug.Log($"Exception caught and logged in AcQuery.getUsersCountAsync{Environment.NewLine}{ecx.Message}");
369  }
370 
371  return count;
372  }
373 
378 
379  public static async Task<int> getDepotsCountAsync()
383  {
384  int count = -1; // assume failure
385  try
386  {
387  AcResult r = await AcCommand.runAsync("show -fx depots").ConfigureAwait(false);
388  if (r != null && r.RetVal == 0)
389  {
390  XElement t = XElement.Parse(r.CmdResult);
391  count = t.Elements("Element").Count();
392  }
393  }
394 
395  catch (AcUtilsException ecx)
396  {
397  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getDepotsCountAsync{Environment.NewLine}{ecx.Message}");
398  }
399 
400  catch (Exception ecx)
401  {
402  AcDebug.Log($"Exception caught and logged in AcQuery.getDepotsCountAsync{Environment.NewLine}{ecx.Message}");
403  }
404 
405  return count;
406  }
407 
412 
413  public static async Task<int> getDynStreamsCountAsync()
417  {
418  int count = -1; // assume failure
419  try
420  {
421  AcResult r = await AcCommand.runAsync("show -fx -d streams").ConfigureAwait(false);
422  if (r != null && r.RetVal == 0)
423  {
424  XElement s = XElement.Parse(r.CmdResult);
425  count = (from d in s.Elements("stream") where d.Attribute("isDynamic").Value == "true" select d).Count();
426  }
427  }
428 
429  catch (AcUtilsException ecx)
430  {
431  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getDynStreamsCountAsync{Environment.NewLine}{ecx.Message}");
432  }
433 
434  catch (Exception ecx)
435  {
436  AcDebug.Log($"Exception caught and logged in AcQuery.getDynStreamsCountAsync{Environment.NewLine}{ecx.Message}");
437  }
438 
439  return count;
440  }
441 
446 
447  public static async Task<int> getTotalStreamsCountAsync()
451  {
452  int count = -1; // assume failure
453  try
454  {
455  AcResult r = await AcCommand.runAsync("show -fix streams").ConfigureAwait(false);
456  if (r != null && r.RetVal == 0)
457  {
458  XElement t = XElement.Parse(r.CmdResult);
459  count = t.Elements("stream").Count();
460  }
461  }
462 
463  catch (AcUtilsException ecx)
464  {
465  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getTotalStreamsCountAsync{Environment.NewLine}{ecx.Message}");
466  }
467 
468  catch (Exception ecx)
469  {
470  AcDebug.Log($"Exception caught and logged in AcQuery.getTotalStreamsCountAsync{Environment.NewLine}{ecx.Message}");
471  }
472 
473  return count;
474  }
475 
480 
481  public static async Task<int> getStreamsWithDefaultGroupCountAsync()
485  {
486  int count = -1; // assume failure
487  try
488  {
489  AcResult r = await AcCommand.runAsync("show -fx -d streams").ConfigureAwait(false);
490  if (r != null && r.RetVal == 0)
491  {
492  XElement t = XElement.Parse(r.CmdResult);
493  count = t.Elements("stream").Count();
494  }
495  }
496 
497  catch (AcUtilsException ecx)
498  {
499  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getStreamsWithDefaultGroupCountAsync{Environment.NewLine}{ecx.Message}");
500  }
501 
502  catch (Exception ecx)
503  {
504  AcDebug.Log($"Exception caught and logged in AcQuery.getStreamsWithDefaultGroupCountAsync{Environment.NewLine}{ecx.Message}");
505  }
506 
507  return count;
508  }
509 
514 
515  public static async Task<int> getTotalWorkspaceCountAsync()
519  {
520  int count = -1; // assume failure
521  try
522  {
523  AcResult r = await AcCommand.runAsync("show -fix -a wspaces").ConfigureAwait(false);
524  if (r != null && r.RetVal == 0)
525  {
526  XElement t = XElement.Parse(r.CmdResult);
527  count = t.Elements("Element").Count();
528  }
529  }
530 
531  catch (AcUtilsException ecx)
532  {
533  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getTotalWorkspaceCountAsync{Environment.NewLine}{ecx.Message}");
534  }
535 
536  catch (Exception ecx)
537  {
538  AcDebug.Log($"Exception caught and logged in AcQuery.getTotalWorkspaceCountAsync{Environment.NewLine}{ecx.Message}");
539  }
540 
541  return count;
542  }
543 
551  public static bool getAcGUIpath(out string path)
552  {
553  bool error = false; // assume success
554  path = null;
555  string temp = String.Empty;
556  try
557  {
558  using (Process process = new Process())
559  {
560  process.StartInfo.RedirectStandardOutput = true;
561  process.StartInfo.CreateNoWindow = true;
562  process.StartInfo.UseShellExecute = false;
563  process.StartInfo.Arguments = "acgui.exe";
564  process.StartInfo.FileName = "where";
565  process.Start();
566  temp = process.StandardOutput.ReadToEnd();
567  process.WaitForExit();
568  }
569  }
570 
571  catch (Exception ecx)
572  {
573  AcDebug.Log($"Exception caught and logged in AcQuery.getAcGUIpath{Environment.NewLine}{ecx.Message}");
574  error = true;
575  }
576 
577  bool result = (!error && !String.IsNullOrEmpty(temp));
578  if (result)
579  path = temp.Substring(0, temp.IndexOf('\r'));
580  return result;
581  }
582 
589  private static bool getAcClientCnfPath(out string path)
590  {
591  path = String.Empty;
592  string temp;
593  bool ret = getAcGUIpath(out temp);
594  if (ret)
595  {
596  string dir = Path.GetDirectoryName(temp);
597  path = Path.Combine(dir, "acclient.cnf");
598  return true;
599  }
600 
601  return false;
602  }
603 
611  public static bool getServerFromAcClientCnf(out string server)
612  {
613  server = null;
614  FileStream fs = null;
615  try
616  {
617  string cnfFile;
618  if (getAcClientCnfPath(out cnfFile))
619  {
620  fs = new FileStream(cnfFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
621  using (StreamReader sr = new StreamReader(fs))
622  {
623  string line = sr.ReadLine();
624  string[] arr = line.Split('=');
625  server = arr[1].Trim();
626  }
627 
628  return true;
629  }
630  }
631 
632  catch (Exception ecx)
633  {
634  AcDebug.Log($"Exception caught and logged in AcQuery.getServerFromAcClientCnf{Environment.NewLine}{ecx.Message}");
635  }
636 
637  finally // avoids CA2202: Do not dispose objects multiple times
638  {
639  if (fs != null) fs.Dispose();
640  }
641 
642  return false;
643  }
644 
649 
650  public static async Task<List<string>> getDepotNameListAsync()
653  {
654  List<string> depots = null;
655  AcResult result = null;
656  try { result = await AcCommand.runAsync("show -fx depots").ConfigureAwait(false); }
657 
658  catch (AcUtilsException ecx)
659  {
660  AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getDepotNameListAsync{Environment.NewLine}{ecx.Message}");
661  }
662 
663  if (result != null && result.RetVal == 0) // if command succeeded
664  {
665  XElement xml = XElement.Parse(result.CmdResult);
666  IEnumerable<XElement> query = from e in xml.Elements("Element")
667  select e;
668  int num = query.Count();
669  depots = new List<string>(num);
670  foreach (XElement n in query)
671  depots.Add((string)n.Attribute("Name"));
672 
673  depots.Sort();
674  }
675 
676  return depots;
677  }
678  }
679 }
static async Task< string > getPrincipalAsync()
Determines if the current user is logged into AccuRev and, if so, retrieves their principal name...
Definition: AcQuery.cs:49
static async Task< int > getTotalStreamsCountAsync()
Get the total number of streams (including workspace streams) in the repository including those that ...
Definition: AcQuery.cs:450
AccuRev program return value and command result.
Definition: AcCommand.cs:29
static async Task< int > getDepotsCountAsync()
Get the number of active depots in the repository.
Definition: AcQuery.cs:382
static bool getAcGUIpath(out string path)
Determine if acgui.exe is found in the Path and thus can be spawned.
Definition: AcQuery.cs:551
static bool getAcClientCnfPath(out string path)
Helper function for getServerFromAcClientCnf returns the full path to acclient.cnf on the host machin...
Definition: AcQuery.cs:589
static async Task< int > getUsersCountAsync(bool includeDeactivated=false)
Get the number of active users.
Definition: AcQuery.cs:348
static async Task< int[]> getBackedVersionAsync(string realverspec, AcDepot depot, string depotrelpath)
For the real version specified in the argument list, get the real stream/version for the version in t...
Definition: AcQuery.cs:167
A depot object that defines the attributes of an AccuRev depot.
Definition: AcDepots.cs:49
static async Task< int > getTotalWorkspaceCountAsync()
Get the total number of workspaces in the repository including those that are hidden.
Definition: AcQuery.cs:518
static async Task< int > getStreamsWithDefaultGroupCountAsync()
Get the number of streams (including workspace streams) in the repository that have a default group...
Definition: AcQuery.cs:484
string CmdResult
The command result (usually XML) emitted by AccuRev.
Definition: AcCommand.cs:70
int RetVal
The AccuRev program return value for the command, otherwise minus one (-1) on error.
Definition: AcCommand.cs:61
static void Log(string message, bool formatting=true)
Write the message text to STDOUT, to weekly log files located in %LOCALAPPDATA%\AcTools\Logs, and to trigger.log in the AccuRev server's ..storage\site_slice\logs folder in the case of triggers.
Definition: AcDebug.cs:378
static T getAppConfigSetting< T >(string key)
Type safe way to retrieve values from .exe.config files.
Definition: AcQuery.cs:268
static bool getServerFromAcClientCnf(out string server)
Get the default AccuRev server from acclient.cnf. The default server is the first line in the file...
Definition: AcQuery.cs:611
Exception thrown when an AccuRev command fails. The AccuRev program return value is zero (0) on succe...
static async Task< string > getCatFileAsync(int eid, AcDepot depot, string ver_spec)
Use to retrieve the contents of a text file under version control.
Definition: AcQuery.cs:119
static async Task< int > getDynStreamsCountAsync()
Get the number of dynamic streams in the repository that have a default group.
Definition: AcQuery.cs:416
static async Task< Tuple< string, int > > getElementNameAsync(string stream, int EID)
Get the depot-relative path for the element in stream with EID. Also returns the element's parent fol...
Definition: AcQuery.cs:233
AccuRev command processing.
Definition: AcCommand.cs:138
static async Task< AcResult > runAsync(string command, ICmdValidate validator=null)
Run the AccuRev command asynchronously with non-blocking I/O.
Definition: AcCommand.cs:184
Use to log and display error and general purpose text messages, and to save the XML param data sent b...
Definition: AcDebug.cs:100
static async Task< int[]> getAccuRevVersionAsync()
Retrieves the AccuRev program major, minor and patch version numbers.
Definition: AcQuery.cs:293
Miscellaneous stuff that didn't fit in elsewhere.
Definition: AcQuery.cs:32
static async Task< List< string > > getDepotNameListAsync()
Get the list of depot names in sorted order.
Definition: AcQuery.cs:652