17 using System.Collections.Generic;
48 [DebuggerDisplay(
"{ToString(\"lv\")}")]
49 public sealed
class AcDepot : IFormattable, IEquatable<AcDepot>, IComparable<AcDepot>, IComparable
51 #region class variables
55 private bool _exclusiveLocking;
57 private bool _dynamicOnly;
58 private bool _includeHidden;
60 [NonSerialized]
private Task<MultiValueDictionary<int, int>> _hierarchy;
61 [NonSerialized]
private object _hierSync = null;
62 [NonSerialized]
private bool _hierInit;
65 #region object construction:
68 internal AcDepot(
bool dynamicOnly,
bool includeHidden)
75 _dynamicOnly = dynamicOnly;
76 _includeHidden = includeHidden;
86 public AcDepot(
string name,
bool dynamicOnly =
false,
bool includeHidden =
false)
87 : this(dynamicOnly, includeHidden)
99 public AcDepot(
int id,
bool dynamicOnly =
false,
bool includeHidden =
false)
100 : this(dynamicOnly, includeHidden)
120 if (r != null && r.
RetVal == 0)
122 XElement xml = XElement.Parse(r.
CmdResult);
123 IEnumerable<XElement> filter = null;
125 filter =
from element in xml.Elements(
"Element")
126 where (
int)element.Attribute(
"Number") == _id
129 filter =
from element in xml.Elements(
"Element")
130 where (
string)element.Attribute(
"Name") == _name
133 XElement e = filter.SingleOrDefault();
136 ID = (int)e.Attribute(
"Number");
137 Name = (string)e.Attribute(
"Name");
138 Slice = (int)e.Attribute(
"Slice");
140 string temp = (string)e.Attribute(
"case");
142 _streams =
new AcStreams(_dynamicOnly, _includeHidden);
150 AcDebug.
Log($
"AcUtilsException caught and logged in AcDepot.initAsync{Environment.NewLine}{ecx.Message}");
153 catch (Exception ecx)
155 AcDebug.
Log($
"Exception caught and logged in AcDepot.initAsync{Environment.NewLine}{ecx.Message}");
163 #region Equality comparison
174 if (ReferenceEquals(other, null))
return false;
175 if (ReferenceEquals(
this, other))
return true;
176 return ID == other.
ID;
183 public override bool Equals(
object other)
185 if (ReferenceEquals(other, null))
return false;
186 if (ReferenceEquals(
this, other))
return true;
187 if (GetType() != other.GetType())
return false;
202 #region Order comparison
214 if (
AcDepot.ReferenceEquals(
this, other))
217 result = String.Compare(
Name, other.
Name);
228 int IComparable.CompareTo(
object other)
231 throw new ArgumentException(
"Argument is not an AcDepot",
"other");
244 internal set { _id = value; }
252 get {
return _name ?? String.Empty; }
253 internal set { _name = value; }
261 get {
return _slice; }
262 internal set { _slice = value; }
270 get {
return _exclusiveLocking; }
271 internal set { _exclusiveLocking = value; }
279 get {
return _case; }
280 internal set { _case = value; }
286 public IEnumerable<AcStream>
Streams
288 get {
return _streams; }
322 AcStream stream = _streams.Where(s => s.ID > 1).SingleOrDefault(s => s.Name == name);
338 AcStream stream = _streams.Where(s => s.ID > 1).SingleOrDefault(s => s.ID == ID);
369 var children = await
getChildrenAsync(stream, includeWSpaces).ConfigureAwait(
false);
370 if (children == null)
return false;
371 if (children.Item1 == null)
return false;
372 if (children.Item1 ==
true)
373 foreach (
AcStream child
in children.Item2)
410 IList<AcStream> children = null;
412 return Tuple.Create((
bool?)
false, children);
417 await LazyInitializer.EnsureInitialized(ref _hierarchy, ref _hierInit, ref _hierSync,
418 async () => await
getHierarchyAsync(includeWSpaces).ConfigureAwait(
false)).ConfigureAwait(
false);
419 if (_hierarchy == null)
420 return Tuple.Create(ret, children);
422 IReadOnlyCollection<int> list = null;
423 ret = _hierarchy.Result.TryGetValue(stream.
ID, out list);
426 children =
new List<AcStream>(list.Count);
427 foreach (
int id in list)
434 return Tuple.Create(ret, children);
453 private async Task<MultiValueDictionary<int, int>>
getHierarchyAsync(
bool includeWSpaces =
false)
455 MultiValueDictionary<int, int> hierarchy = null;
459 .ConfigureAwait(
false);
460 if (r != null && r.
RetVal == 0)
462 XElement xml = XElement.Parse(r.
CmdResult);
463 IEnumerable<XElement> filter;
465 filter =
from s in xml.Elements(
"stream")
468 filter =
from s in xml.Elements(
"stream")
469 where (
string)s.Attribute(
"type") !=
"workspace"
472 int capacity = filter.Count();
473 hierarchy =
new MultiValueDictionary<int, int>(capacity);
474 foreach (XElement e
in filter)
477 int parent = (
int?)e.Attribute(
"basisStreamNumber") ?? -1;
478 int child = (int)e.Attribute(
"streamNumber");
479 hierarchy.Add(parent, child);
486 AcDebug.
Log($
"AcUtilsException caught and logged in AcDepot.getHierarchyAsync{Environment.NewLine}{ecx.Message}");
490 catch (Exception ecx)
492 AcDebug.
Log($
"Exception caught and logged in AcDepot.getHierarchyAsync{Environment.NewLine}{ecx.Message}");
531 string listfile = null;
534 string appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
535 string actools = Path.Combine(appdata,
"AcTools");
536 string exeroot = String.Empty;
537 using (Process currentProcess = Process.GetCurrentProcess())
539 ProcessModule pm = currentProcess.MainModule;
540 exeroot = Path.GetFileNameWithoutExtension(pm.ModuleName);
543 string progfolder = Path.Combine(actools, exeroot);
544 string temp = Path.Combine(progfolder,
Name);
545 string file = Path.ChangeExtension(temp,
"streams");
546 if (File.Exists(file))
550 catch (Exception ecx)
552 AcDebug.
Log($
"Exception caught and logged in AcDepot.listFile{Environment.NewLine}{ecx.Message}");
559 public string ToString(
string format, IFormatProvider provider)
575 if (provider != null)
577 ICustomFormatter fmt = provider.GetFormat(this.GetType()) as ICustomFormatter;
579 return fmt.Format(format,
this, provider);
582 if (String.IsNullOrEmpty(format))
585 switch (format.ToUpperInvariant())
590 return $
"{Name} ({ID}), slice {Slice}, {Case}{(ExclusiveLocking ? ", exclusive locking
" : String.Empty)}";
592 return ID.ToString();
594 return Slice.ToString();
598 return Case.ToString();
600 throw new FormatException($
"The {format} format string is not supported.");
605 public string ToString(
string format)
624 #region class variables
626 [NonSerialized]
private Task<bool> _depotPermObj;
627 [NonSerialized]
private object _permSync = null;
628 [NonSerialized]
private bool _permInit;
629 private bool _dynamicOnly;
630 private bool _includeHidden;
631 [NonSerialized]
private readonly
object _locker =
new object();
632 [NonSerialized]
private int _counter;
635 #region object construction:
652 public AcDepots(
bool dynamicOnly =
false,
bool includeHidden =
false)
654 _dynamicOnly = dynamicOnly;
655 _includeHidden = includeHidden;
720 if (r != null && r.
RetVal == 0)
722 XElement xml = XElement.Parse(r.
CmdResult);
723 IEnumerable<XElement> query = null;
724 if (depotsCol == null)
725 query =
from e in xml.Elements(
"Element") select e;
727 query =
from e in xml.Elements(
"Element")
728 where depotsCol.OfType<
DepotElement>().Any(de => de.Depot == (
string)e.Attribute(
"Name"))
731 int num = query.Count();
732 List<Task<bool>> tasks =
new List<Task<bool>>(num);
733 Func<Task<bool>,
bool> cf = t =>
736 if (res && progress != null) progress.Report(Interlocked.Increment(ref _counter));
740 foreach (XElement e
in query)
743 depot.
ID = (int)e.Attribute(
"Number");
744 depot.
Name = (string)e.Attribute(
"Name");
745 depot.
Slice = (int)e.Attribute(
"Slice");
747 string temp = (string)e.Attribute(
"case");
749 depot._streams =
new AcStreams(_dynamicOnly, _includeHidden);
750 lock (_locker) { Add(depot); }
751 Task<bool> t = depot._streams.
initAsync(depot, depot.
listFile()).ContinueWith(cf);
755 bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(
false);
756 ret = (arr != null && arr.All(n => n ==
true));
762 AcDebug.
Log($
"AcUtilsException caught and logged in AcDepots.initAsync{Environment.NewLine}{ecx.Message}");
765 catch (Exception ecx)
767 AcDebug.
Log($
"Exception caught and logged in AcDepots.initAsync{Environment.NewLine}{ecx.Message}");
775 #pragma warning disable 0642
789 await LazyInitializer.EnsureInitialized(ref _depotPermObj, ref _permInit, ref _permSync,
793 return await _permissions.initAsync().ConfigureAwait(
false);
794 }).ConfigureAwait(
false);
796 if (_depotPermObj.Result ==
false)
802 List<string> canView =
new List<string>();
806 bool isInheritable =
false;
809 if (_permissions.Any(p =>
811 bool all = (p.Type == PermType.user && p.Rights == PermRights.all &&
812 p.AppliesTo == user.Principal.Name && p.Name == depot.Name);
814 isInheritable = (p.Inheritable == true && p.Type == PermType.user && p.Rights == PermRights.all &&
815 p.AppliesTo == user.Principal.Name && p.Name == depot.Name);
819 canView.Add($
"{depot.Name}{(isInheritable ? "+
" : String.Empty)}");
821 else if (_permissions.Any(p =>
823 return (p.Type == PermType.user && p.Rights == PermRights.none &&
824 p.AppliesTo == user.Principal.Name && p.Name == depot.Name);
832 bool none = _permissions.Any(p =>
835 p.Type ==
PermType.group && members.Any(m => p.AppliesTo == m));
841 all = _permissions.Any(p =>
844 p.Type ==
PermType.group && members.Any(m => p.AppliesTo == m));
852 isInheritable = _permissions.Any(p =>
854 return (p.Inheritable ==
true && p.Name == depot.
Name &&
855 p.Type ==
PermType.group && members.Any(m => p.AppliesTo == m));
858 canView.Add($
"{depot.Name}{(isInheritable ? "+
" : String.Empty)}");
863 IEnumerable<string> e = canView.OrderBy(n => n);
864 string depots = String.Join(
", ", e);
875 return this.SingleOrDefault(n => n.Name == name);
885 return this.SingleOrDefault(n => n.ID == ID);
896 from s in d.Streams.Where(n => n.Name == name)
897 select d).SingleOrDefault();
909 from s in d.Streams.Where(n => n.Name == name)
910 select s).SingleOrDefault();
AcDepot getDepot(string name)
Get the AcDepot object for depot name.
int Slice
Depot's slice number.
AcPrincipal Principal
AccuRev principal attributes name, ID, and status (active or inactive), and optionally their group me...
AccuRev program return value and command result.
int BasisID
Basis stream ID number.
AcDepot(bool dynamicOnly, bool includeHidden)
Constructor used during AcDepots list construction. It is called internally and not by user code...
async Task< bool > initAsync(AcDepot depot, string listfile=null)
Populate this container with AcStream objects as per constructor parameters. AcStream objects are ins...
PermRights
Whether permission rights to Name in AppliesTo is all or none.
CaseSensitivity
Indicates whether the depot is case sensitive or insensitive (defined when the depot is created)...
AcDepot getDepot(int ID)
Get the AcDepot object for depot ID number.
The list of AccuRev depots from
.exe.config.
AcStream getStream(int ID)
Get the AcStream object with stream ID number.
A user's AccuRev principal attributes name, ID, and status (active or inactive). In addition...
async Task< string > canViewAsync(AcUser user)
Get the list of depots user has permission to view based on their principal name and group membership...
IEnumerable< AcStream > Streams
The list of streams in this depot.
An AccuRev depot from the Depots section in
.exe.config.
async Task< Tuple< bool?, IList< AcStream > > > getChildrenAsync(AcStream stream, bool includeWSpaces=false)
Get the list of child streams that have stream as their immediate parent (basis) stream.
async Task< bool > initAsync(DepotsCollection depotsCol=null, IProgress< int > progress=null)
Populate this container with AcDepot objects as per constructor parameters.
A depot object that defines the attributes of an AccuRev depot.
async Task< MultiValueDictionary< int, int > > getHierarchyAsync(bool includeWSpaces=false)
Get the depot's stream and workspace (optional) hierarchy relationship data from AccuRev. This method is called internally and not by user code.
async Task< bool > forStreamAndAllChildrenAsync(AcStream stream, Action< AcStream > cb, bool includeWSpaces=false)
Run the specified action cb for stream and all child streams in its hierarchy.
async Task< bool > initAsync()
Initialize this AcDepot object with data from AccuRev as per constructor parameter's depot name or ID...
AcDepots(bool dynamicOnly=false, bool includeHidden=false)
A container of AcDepot objects that define AccuRev depots in the repository.
PermKind
Whether permissions pertain to depots or streams. Set when the permission is created by the setacl co...
A stream object that defines the attributes of an AccuRev stream. AcStream objects are instantiated d...
string CmdResult
The command result (usually XML) emitted by AccuRev.
int RetVal
The AccuRev program return value for the command, otherwise minus one (-1) on error.
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.
AcStream getStream(string name)
Get the AcStream object for stream name.
StreamType Type
The kind of stream: unknown, normal, dynamic, regular, workspace, snapshot, passthru, passthrough, gated or staging.
AcStream getStream(string name)
Get the AcStream object for stream name.
AcDepot(string name, bool dynamicOnly=false, bool includeHidden=false)
Constructor for specifying the depot name.
override bool Equals(object other)
Overridden to determine equality.
AcStream getBasis(int ID)
Get the basis (parent) stream for stream ID number.
Exception thrown when an AccuRev command fails. The AccuRev program return value is zero (0) on succe...
StreamType
The type of stream.
AcStream getBasis(string name)
Get the basis (parent) stream for stream name.
AccuRev command processing.
static async Task< AcResult > runAsync(string command, ICmdValidate validator=null)
Run the AccuRev command asynchronously with non-blocking I/O.
int CompareTo(AcDepot other)
Generic IComparable implementation (default) for comparing AcDepot objects to sort by depot name...
AcDepot(int id, bool dynamicOnly=false, bool includeHidden=false)
Constructor for specifying the depot ID number.
Use to log and display error and general purpose text messages, and to save the XML param data sent b...
override int GetHashCode()
Override appropriate for type AcDepot.
A container of AcDepot objects that define AccuRev depots in the repository.
string listFile()
When this file exists (created manually), it is used as the list-file to populate the depot with sele...
AcDepot getDepotForStream(string name)
Get the AcDepot object for stream name.
bool ExclusiveLocking
Whether or not all workspaces created for this depot use exclusive file locking.
A container of AcPermission objects that define AccuRev access control list (ACL) entries...
SortedSet< string > Members
The list of groups a user has membership in, or the list of principals (users and groups) in a group...
PermType
Whether AppliesTo is the principal name for a group, user, or builtin type.
A container of AcStream objects that define AccuRev streams. AcStream objects are instantiated during...
string ToString(string format, IFormatProvider provider)
The ToString implementation.
bool Equals(AcDepot other)
IEquatable implementation to determine the equality of instances of type AcDepot. Uses the depot ID n...
CaseSensitivity Case
Whether the depot is case sensitive or insensitive.