AcUtils
A high performance abstraction layer for AccuRev
AcRules.cs
Go to the documentation of this file.
1 
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 using System.Threading;
20 using System.Threading.Tasks;
21 using System.Xml.Linq;
22 
23 namespace AcUtils
24 {
25  #region enums
26 
27  public enum RuleKind {
34  unknown,
37  clear,
40  incl,
43  incldo,
46  excl
47  };
49  #endregion
50 
57  [Serializable]
58  public sealed class AcRule : IFormattable, IEquatable<AcRule>, IComparable<AcRule>, IComparable
59  {
60  #region class variables
61  private RuleKind _kind = RuleKind.unknown;
62  private ElementType _type = ElementType.unknown;
63  private string _location;
64  private string _setInStream;
65  private string _xlinkToStream;
66  #endregion
67 
71  internal AcRule() { }
72 
73  #region Equality comparison
74 
76  public bool Equals(AcRule other)
84  {
85  if (ReferenceEquals(other, null)) return false;
86  if (ReferenceEquals(this, other)) return true;
87  var left = Tuple.Create(Kind, Location, SetInStream);
88  var right = Tuple.Create(other.Kind, other.Location, other.SetInStream);
89  return left.Equals(right);
90  }
91 
96  public override bool Equals(object other)
97  {
98  if (ReferenceEquals(other, null)) return false;
99  if (ReferenceEquals(this, other)) return true;
100  if (GetType() != other.GetType()) return false;
101  return this.Equals(other as AcRule);
102  }
103 
109  public override int GetHashCode()
110  {
111  var hash = Tuple.Create(Kind, Location, SetInStream);
112  return hash.GetHashCode();
113  }
115  #endregion
116 
117  #region Order comparison
118 
120 
128  public int CompareTo(AcRule other)
129  {
130  int result;
131  if (AcRule.ReferenceEquals(this, other))
132  result = 0;
133  else
134  {
135  result = String.Compare(SetInStream, other.SetInStream);
136  if (result == 0)
137  result = String.Compare(Location, other.Location);
138  }
139 
140  return result;
141  }
142 
149  int IComparable.CompareTo(object other)
150  {
151  if (!(other is AcRule))
152  throw new ArgumentException("Argument is not an AcRule", "other");
153  AcRule o = (AcRule)other;
154  return this.CompareTo(o);
155  }
157  #endregion
158 
162  public RuleKind Kind
163  {
164  get { return _kind; }
165  internal set { _kind = value; }
166  }
167 
171  public ElementType Type
172  {
173  get { return _type; }
174  internal set { _type = value; }
175  }
176 
180  public string Location
181  {
182  get { return _location ?? String.Empty; }
183  internal set { _location = value; }
184  }
185 
189  public string SetInStream
190  {
191  get { return _setInStream ?? String.Empty; }
192  internal set { _setInStream = value; }
193  }
194 
198  public string XlinkToStream
199  {
200  get { return _xlinkToStream ?? String.Empty; }
201  internal set { _xlinkToStream = value; }
202  }
203 
204  #region ToString
205  public string ToString(string format, IFormatProvider provider)
220  {
221  if (provider != null)
222  {
223  ICustomFormatter fmt = provider.GetFormat(this.GetType()) as ICustomFormatter;
224  if (fmt != null)
225  return fmt.Format(format, this, provider);
226  }
227 
228  if (String.IsNullOrEmpty(format))
229  format = "G";
230 
231  switch (format.ToUpperInvariant())
232  {
233  case "G":
234  {
235  string text;
236  if (!String.IsNullOrEmpty(_xlinkToStream))
237  text = $"SetInStream: {SetInStream}{Environment.NewLine}" +
238  $"Cross-link (basis): {XlinkToStream}{Environment.NewLine}" +
239  $"Location: {Location}{Environment.NewLine}" +
240  $"Rule kind: {Kind}{Environment.NewLine}" +
241  $"Element type: {Type}{Environment.NewLine}";
242  else
243  text = $"SetInStream: {SetInStream}{Environment.NewLine}" +
244  $"Location: {Location}{Environment.NewLine}" +
245  $"Rule kind: {Kind}{Environment.NewLine}" +
246  $"Element type: {Type}{Environment.NewLine}";
247  return text;
248  }
249  case "K": // kind of rule in use
250  return Kind.ToString();
251  case "T": // type of element the rule was placed on
252  return Type.ToString();
253  case "L": // depot-relative path of the element the rule affects
254  return Location;
255  case "S": // stream or workspace the rule is applied to
256  return SetInStream;
257  case "X": // if cross-link the basis stream for the SetInStream
258  return XlinkToStream;
259  default:
260  throw new FormatException($"The {format} format string is not supported.");
261  }
262  }
263 
264  // Calls ToString(string, IFormatProvider) version with a null IFormatProvider argument.
265  public string ToString(string format)
266  {
267  return ToString(format, null);
268  }
269 
270  // Calls ToString(string, IFormatProvider) version with the general format and a null IFormatProvider argument.
271  public override string ToString()
272  {
273  return ToString("G", null);
274  }
275  #endregion ToString
276  }
277 
281 
283  [Serializable]
284  public sealed class AcRules : List<AcRule>
285  {
286  private bool _explicitOnly;
287  [NonSerialized] private readonly object _locker = new object(); // token for lock keyword scope
288  [NonSerialized] private int _counter; // used to report initialization progress back to the caller
289 
290  #region object construction:
291 
293 
317  public AcRules(bool explicitOnly = false)
318  {
319  _explicitOnly = explicitOnly;
320  }
321 
331 
354  public async Task<bool> initAsync(AcStream stream)
355  {
356  bool ret = false; // assume failure
357  try
358  {
359  AcResult r = await AcCommand.runAsync($@"lsrules -s ""{stream}"" {(_explicitOnly ? "-d" : String.Empty)} -fx")
360  .ConfigureAwait(false);
361  if (r != null && r.RetVal == 0)
362  {
363  XElement xml = XElement.Parse(r.CmdResult);
364  foreach (XElement e in xml.Elements("element"))
365  {
366  AcRule rule = new AcRule();
367  string kind = (string)e.Attribute("kind");
368  rule.Kind = (RuleKind)Enum.Parse(typeof(RuleKind), kind);
369  string type = (string)e.Attribute("elemType");
370  rule.Type = (ElementType)Enum.Parse(typeof(ElementType), type);
371  rule.Location = (string)e.Attribute("location");
372  rule.SetInStream = (string)e.Attribute("setInStream");
373  rule.XlinkToStream = (string)e.Attribute("xlinkToStream") ?? String.Empty;
374  lock (_locker) { Add(rule); }
375  }
376 
377  ret = true; // operation succeeded
378  }
379  }
380 
381  catch (AcUtilsException ecx)
382  {
383  AcDebug.Log($"AcUtilsException caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}");
384  }
385 
386  catch (Exception ecx)
387  {
388  AcDebug.Log($"Exception caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}");
389  }
390 
391  return ret;
392  }
393 
403  public async Task<bool> initAsync(AcDepot depot, IProgress<int> progress = null)
404  {
405  bool ret = false; // assume failure
406  try
407  {
408  int num = depot.Streams.Count();
409  List<Task<bool>> tasks = new List<Task<bool>>(num);
410  Func<Task<bool>, bool> cf = t =>
411  {
412  bool res = t.Result;
413  if (res && progress != null) progress.Report(Interlocked.Increment(ref _counter));
414  return res;
415  };
416 
417  foreach (AcStream stream in depot.Streams)
418  {
419  Task<bool> t = initAsync(stream).ContinueWith(cf);
420  tasks.Add(t);
421  }
422 
423  bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false);
424  ret = (arr != null && arr.All(n => n == true)); // true if all succeeded
425  }
426 
427  catch (Exception ecx)
428  {
429  AcDebug.Log($"Exception caught and logged in AcRules.initAsync(AcDepot){Environment.NewLine}{ecx.Message}");
430  }
431 
432  return ret;
433  }
434 
444  public async Task<bool> initAsync(StreamsCollection streamsCol, IProgress<int> progress = null)
445  {
446  bool ret = false; // assume failure
447  try
448  {
449  AcDepots depots = new AcDepots();
450  if (!(await depots.initAsync(null, progress).ConfigureAwait(false))) return false;
451  int num = 0; // get number of streams for tasks list
452  foreach (AcDepot depot in depots)
453  {
454  IEnumerable<AcStream> filter = depot.Streams.Where(s =>
455  streamsCol.OfType<StreamElement>().Any(se => s.Name == se.Stream));
456  num += filter.Count();
457  }
458 
459  List<Task<bool>> tasks = new List<Task<bool>>(num);
460  Func<Task<bool>, bool> cf = t =>
461  {
462  bool res = t.Result;
463  if (res && progress != null) progress.Report(Interlocked.Increment(ref _counter));
464  return res;
465  };
466 
467  foreach (AcDepot depot in depots)
468  {
469  IEnumerable<AcStream> filter = depot.Streams.Where(s =>
470  streamsCol.OfType<StreamElement>().Any(se => s.Name == se.Stream));
471  foreach (AcStream stream in filter)
472  {
473  Task<bool> t = initAsync(stream).ContinueWith(cf);
474  tasks.Add(t);
475  }
476  }
477 
478  bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false);
479  ret = (arr != null && arr.All(n => n == true)); // true if all succeeded
480  }
481 
482  catch (Exception ecx)
483  {
484  AcDebug.Log($"Exception caught and logged in AcRules.initAsync(StreamsCollection){Environment.NewLine}{ecx.Message}");
485  }
486 
487  return ret;
488  }
489 
499  public async Task<bool> initAsync(DepotsCollection depotsCol, IProgress<int> progress = null)
500  {
501  bool ret = false; // assume failure
502  try
503  {
504  AcDepots depots = new AcDepots();
505  if (!(await depots.initAsync(depotsCol, progress).ConfigureAwait(false))) return false;
506  int num = 0; // get number of streams for tasks list
507  foreach (AcDepot depot in depots)
508  num += depot.Streams.Count();
509  List<Task<bool>> tasks = new List<Task<bool>>(num);
510  Func<Task<bool>, bool> cf = t =>
511  {
512  bool res = t.Result;
513  if (res && progress != null) progress.Report(Interlocked.Increment(ref _counter));
514  return res;
515  };
516 
517  foreach (AcStream stream in depots.SelectMany(d => d.Streams))
518  {
519  Task<bool> t = initAsync(stream).ContinueWith(cf);
520  tasks.Add(t);
521  }
522 
523  bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false);
524  ret = (arr != null && arr.All(n => n == true));
525  }
526 
527  catch (Exception ecx)
528  {
529  AcDebug.Log($"Exception caught and logged in AcRules.initAsync(DepotsCollection){Environment.NewLine}{ecx.Message}");
530  }
531 
532  return ret;
533  }
535  #endregion
536  }
537 }
string XlinkToStream
In the case of a cross-link this is the basis stream for SetInStream.
Definition: AcRules.cs:199
bool Equals(AcRule other)
IEquatable implementation to determine the equality of instances of type AcRule. Values used to compa...
Definition: AcRules.cs:83
AccuRev program return value and command result.
Definition: AcCommand.cs:29
ElementType
Indicates the element's type. By default, AccuRev determines the element type for a newly created ver...
Definition: Stat.cs:35
ElementType Type
Type of element the rule was placed on: dir, text, binary, ptext, elink, or slink.
Definition: AcRules.cs:172
The attributes of a stream or workspace include or exclude rule: RuleKind, ElementType, location affected by the rule, stream or workspace the rule was applied to, and (if applicable) the basis stream for cross-links.
Definition: AcRules.cs:58
The list of AccuRev depots from .exe.config.
A container of AcRule objects that define the attributes of stream and workspace include and exclude ...
Definition: AcRules.cs:284
IEnumerable< AcStream > Streams
The list of streams in this depot.
Definition: AcDepots.cs:287
async Task< bool > initAsync(StreamsCollection streamsCol, IProgress< int > progress=null)
Populate this container with AcRule objects for all streams in streamsCol as per constructor paramete...
Definition: AcRules.cs:444
async Task< bool > initAsync(AcDepot depot, IProgress< int > progress=null)
Populate this container with AcRule objects for all streams in depot as per constructor parameter exp...
Definition: AcRules.cs:403
int CompareTo(AcRule other)
Generic IComparable implementation (default) for comparing AcRule objects. Sorts by the stream or wor...
Definition: AcRules.cs:128
async Task< bool > initAsync(AcStream stream)
Populate this container with AcRule objects for stream as per constructor parameter explicitOnly...
Definition: AcRules.cs:354
RuleKind Kind
Kind of AccuRev rule in use.
Definition: AcRules.cs:163
async Task< bool > initAsync(DepotsCollection depotsCol=null, IProgress< int > progress=null)
Populate this container with AcDepot objects as per constructor parameters.
Definition: AcDepots.cs:714
A depot object that defines the attributes of an AccuRev depot.
Definition: AcDepots.cs:49
override int GetHashCode()
Override appropriate for type AcRule.
Definition: AcRules.cs:109
AcRule()
Constructor used during AcRules list construction. It is called internally and not by user code...
Definition: AcRules.cs:71
A stream object that defines the attributes of an AccuRev stream. AcStream objects are instantiated d...
Definition: AcStreams.cs:74
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
AcRules(bool explicitOnly=false)
A container of AcRule objects that define the attributes of stream and workspace include and exclude ...
Definition: AcRules.cs:317
RuleKind
The kind of AccuRev rule.
Definition: AcRules.cs:31
string SetInStream
Name of stream or workspace the rule is applied to.
Definition: AcRules.cs:190
Exception thrown when an AccuRev command fails. The AccuRev program return value is zero (0) on succe...
AccuRev command processing.
Definition: AcCommand.cs:138
An AccuRev stream from the Streams section in .exe.config.
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
override bool Equals(object other)
Overridden to determine equality.
Definition: AcRules.cs:96
A container of AcDepot objects that define AccuRev depots in the repository.
Definition: AcDepots.cs:622
string ToString(string format, IFormatProvider provider)
The ToString implementation.
Definition: AcRules.cs:219
The list of AccuRev streams from .exe.config.
async Task< bool > initAsync(DepotsCollection depotsCol, IProgress< int > progress=null)
Populate this container with AcRule objects for all streams in depotsCol as per constructor parameter...
Definition: AcRules.cs:499
string Location
Depot-relative path of the element the rule affects.
Definition: AcRules.cs:181