/// <summary> /// Get the total number of workspaces in the repository including those that are hidden. /// </summary> /// <returns>Total number of workspaces or <em>minus one (-1)</em> on error.</returns> /*! \show_ <tt>show -fix -a wspaces</tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> public static async Task <int> getTotalWorkspaceCountAsync() { int count = -1; // assume failure try { AcResult r = await AcCommand.runAsync("show -fix -a wspaces").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement t = XElement.Parse(r.CmdResult); count = t.Elements("Element").Count(); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getTotalWorkspaceCountAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getTotalWorkspaceCountAsync{Environment.NewLine}{ecx.Message}"); } return(count); }
/// <summary> /// Get user preferences retrieved by way of the \c getpref command. /// </summary> /// <returns>The full path to a temp file with the XML results from the \e getpref command, otherwise \e null on error. /// The caller is responsible for deleting the file.</returns> /*! \getpref_ \c getpref */ /*! \accunote_ When using the AccuRev GUI client, changes in <em>User Preferences</em> do not always persist. * As a workaround, use [setpref](https://www.microfocus.com/documentation/accurev/72/WebHelp/wwhelp/wwhimpl/js/html/wwhelp.htm#href=AccuRev_User_CLI/cli_ref_setpref.html): * -# Exit the AccuRev client. * -# Put the setting\(s\) needed in a file named <tt>set_pref.xml</tt> * -# Open a command window and cd to the folder where the file is located. * -# Run the command <tt>accurev setpref -l set_pref.xml</tt> \(-l switch is a lowercase L\) * -# Run the AccuRev client and verify the setting\(s\). * \verbatim * <AcRequest> * <USE_IGNORE_ELEMS_OPTIMIZATION>true</USE_IGNORE_ELEMS_OPTIMIZATION> * ... * </AcRequest> * \endverbatim */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c getpref command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> private static async Task <string> getPreferencesAsync() { // Putting the XML into a file as opposed to using it directly avoids exceptions thrown // due to illegal characters. Needs further investigation. string tempFile = null; try { AcResult r = await AcCommand.runAsync("getpref").ConfigureAwait(false); if (r != null && r.RetVal == 0) // if command succeeded { tempFile = Path.GetTempFileName(); using (StreamWriter writer = new StreamWriter(tempFile)) { writer.Write(r.CmdResult); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcPreferences.getPreferencesAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) // IOException, DirectoryNotFoundException, PathTooLongException, SecurityException... others { AcDebug.Log($"Exception caught and logged in AcPreferences.getPreferencesAsync{Environment.NewLine}{ecx.Message}"); } return(tempFile); }
/// <summary> /// Get the depot-relative path for the element in \e stream with \e EID. /// Also returns the element's parent folder EID (folder where the element resides). /// </summary> /// <param name="stream">Name of the stream where the element resides.</param> /// <param name="EID">The element ID of the element on which to query.</param> /// <returns>An tuple initialized as <em>{depot-relative path, parent EID}</em> on success, otherwise \e null.</returns> /*! \name_ <tt>name -v \<stream\> -fx -e \<EID\></tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c name command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \code * accurev name -v MARS_MAINT2 -fx -e 13763 * <?xml version="1.0" encoding="utf-8"?> * <AcResponse * Command="name" * TaskId="51498"> * <element * location="\.\scripts\build.xml" * parent_id="12269"/> * </AcResponse> * \endcode */ /*! \accunote_ For the \c name, \c anc and \c cat commands, the validity of the results is guaranteed only if the commands are issued outside a workspace, or in a workspace whose * backing stream is in the same depot for both workspace and the <tt>-v \<ver_spec\></tt> option used. If issued from a workspace that has a different backing stream than * the <tt>-v \<ver_spec\></tt>, provided both workspace and ver_spec share the same depot, the command results can be deemed valid. However, if issued from a workspace whose * backing stream is in a different depot than the <tt>-v \<ver_spec\></tt>, the command results are invalid. Applications should set the default directory to a non-workspace * location prior to issuing these commands. AccuRev defects 18080, 21469, 1097778. */ public static async Task <Tuple <string, int> > getElementNameAsync(string stream, int EID) { Tuple <string, int> ret = null; // depot-relative path, parent folder EID try { AcResult r = await AcCommand.runAsync($@"name -v ""{stream}"" -fx -e {EID}").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); string location = (string)xml.Element("element").Attribute("location"); int parent_id = (int)xml.Element("element").Attribute("parent_id"); ret = Tuple.Create(location, parent_id); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getElementNameAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getElementNameAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Get the list of depot names in sorted order. /// </summary> /// <returns>The list of depot names on success, otherwise \e null on error.</returns> /*! \show_ <tt>show -fx depots</tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> public static async Task <List <string> > getDepotNameListAsync() { List <string> depots = null; AcResult result = null; try { result = await AcCommand.runAsync("show -fx depots").ConfigureAwait(false); } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getDepotNameListAsync{Environment.NewLine}{ecx.Message}"); } if (result != null && result.RetVal == 0) // if command succeeded { XElement xml = XElement.Parse(result.CmdResult); IEnumerable <XElement> query = from e in xml.Elements("Element") select e; int num = query.Count(); depots = new List <string>(num); foreach (XElement n in query) { depots.Add((string)n.Attribute("Name")); } depots.Sort(); } return(depots); }
/// <summary> /// Remove \c lock \e kind on \e stream. /// </summary> /// <param name="stream">Name of stream or workspace to unlock.</param> /// <param name="kind">Type of lock to remove: \e to, \e from, or \e all.</param> /// <returns>\e true if \e stream was unlocked successfully, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c unlock command failure.</exception> /*! \unlock_ <tt>unlock [-kf | -kt] \<stream\></tt> */ public async Task <bool> unlockAsync(string stream, LockKind kind = LockKind.all) { bool ret = false; // assume failure try { string cmd = null; if (kind == LockKind.from) { cmd = $@"unlock -kf ""{stream}"""; } else if (kind == LockKind.to) { cmd = $@"unlock -kt ""{stream}"""; } else if (kind == LockKind.all) { cmd = $@"unlock ""{stream}"""; } AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false); ret = (r != null && r.RetVal == 0); } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException in AcLocks.unlockAsync caught and logged.{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcLock objects on \e streams. /// </summary> /// <param name="streams">Limit the list of locks to those on \e streams only. Stream names in \e streams /// must match their respective AccuRev stream name exactly.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcLocks constructor](@ref AcUtils#AcLocks#AcLocks), initAsync(AcDepot), initAsync(DepotsCollection) */ /*! \show_ <tt>show -fx locks</tt> */ public async Task <bool> initAsync(StreamsCollection streams) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx locks").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> query = from e in xml.Elements("Element") where streams.OfType <StreamElement>().Any(se => se.Stream == (string)e.Attribute("Name")) select e; ret = initList(query); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcLocks.initAsync(StreamsCollection){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcLocks.initAsync(StreamsCollection){Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Get the number of dynamic streams in the repository that have a default group. /// </summary> /// <returns>Number of dynamic streams with a default group or <em>minus one (-1)</em> on error.</returns> /*! \show_ <tt>show -fx -d streams</tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> public static async Task <int> getDynStreamsCountAsync() { int count = -1; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx -d streams").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement s = XElement.Parse(r.CmdResult); count = (from d in s.Elements("stream") where d.Attribute("isDynamic").Value == "true" select d).Count(); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getDynStreamsCountAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getDynStreamsCountAsync{Environment.NewLine}{ecx.Message}"); } return(count); }
/// <summary> /// Use to retrieve the contents of a text file under version control. /// </summary> /// <remarks> /// Puts the content of the specified file in a temporary file. The caller is responsible for deleting the file. /// </remarks> /// <param name="eid">The file's element ID.</param> /// <param name="depot">The depot.</param> /// <param name="ver_spec">The version specification in the numeric or text format, e.g. \c 32/1 or \c PG_MAINT1_barnyrd\4.</param> /// <returns>A string initialized to the name of the temporary file with the contents from the /// AccuRev <tt>cat -v \<ver_spec\> -p \<depot\> -e \<eid\></tt> command on success, otherwise \e null on error. /// </returns> /*! \cat_ <tt>cat -v \<ver_spec\> -p \<depot\> -e \<eid\></tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c cat command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \accunote_ The CLI \c cat command fails on Windows for ptext files larger than 62,733 bytes. Fixed in 6.0. AccuRev defect 28177. */ /*! \accunote_ For the \c name, \c anc and \c cat commands, the validity of the results is guaranteed only if the commands are issued outside a workspace, or in a workspace whose * backing stream is in the same depot for both workspace and the <tt>-v \<ver_spec\></tt> option used. If issued from a workspace that has a different backing stream than * the <tt>-v \<ver_spec\></tt>, provided both workspace and ver_spec share the same depot, the command results can be deemed valid. However, if issued from a workspace whose * backing stream is in a different depot than the <tt>-v \<ver_spec\></tt>, the command results are invalid. Applications should set the default directory to a non-workspace * location prior to issuing these commands. AccuRev defects 18080, 21469, 1097778. */ public static async Task <string> getCatFileAsync(int eid, AcDepot depot, string ver_spec) { string tmpFile = null; try { AcResult r = await AcCommand.runAsync($@"cat -v ""{ver_spec}"" -p ""{depot}"" -e {eid}") .ConfigureAwait(false); if (r != null && r.RetVal == 0) { tmpFile = Path.GetTempFileName(); using (StreamWriter streamWriter = new StreamWriter(tmpFile)) { streamWriter.Write(r.CmdResult); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getCatFileAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) // IOException, DirectoryNotFoundException, PathTooLongException, SecurityException... others { AcDebug.Log($"Exception caught and logged in AcQuery.getCatFileAsync{Environment.NewLine}{ecx.Message}"); } return(tmpFile); }
/// <summary> /// Populate this container with AcStream objects as per constructor parameters. /// AcStream objects are instantiated during AcDepot and AcDepots construction. /// This function is called internally and not by user code. /// </summary> /// <param name="depot">The depot for which streams will be created.</param> /// <param name="listfile">List file <tt>\%APPDATA\%\\AcTools\\<prog_name\>\\<depot_name\>.streams</tt> for the /// <a href="https://www.microfocus.com/documentation/accurev/72/WebHelp/wwhelp/wwhimpl/js/html/wwhelp.htm#href=AccuRev_User_CLI/cli_ref_show.html">show -l <list-file> streams</a> /// command if found, otherwise \e null.<br> /// Example: <tt>"C:\Users\barnyrd\AppData\Roaming\AcTools\FooApp\NEPTUNE.streams"</tt>.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on failure /// to handle a range of exceptions.</exception> /*! \sa [AcStreams constructor](@ref AcUtils#AcStreams#AcStreams) */ /*! \show_ <tt>show \<-fxig|-fxg\> -p \<depot\> [-l listfile] streams</tt> */ /*! \accunote_ The following XML attributes from <tt>show -fx -p \<depot\> streams</tt> may exist depending on the version of AccuRev in use. * They are used internally by AccuRev and are not intended for customer usage. Micro Focus incident #3132463. * - \e eventStream: Efficient way to determine if the server process needs to fire the event trigger processing. * - \e eventStreamHWM: Used by GitCentric to track the high watermark for synchronization. * - \e hasProperties: Efficient way for the GUI to determine if the property icon is displayed in the StreamBrowser. */ internal async Task <bool> initAsync(AcDepot depot, string listfile = null) { bool ret = false; // assume failure try { AcResult result = await AcCommand.runAsync($@"show {(_includeHidden ? "-fxig" : "-fxg")} -p ""{depot}""" + $@"{((listfile == null) ? String.Empty : "-l " + "" + listfile + "")} streams") .ConfigureAwait(false); if (result != null && result.RetVal == 0) { XElement xml = XElement.Parse(result.CmdResult); IEnumerable <XElement> filter = null; if (_dynamicOnly) { filter = from s in xml.Elements("stream") where (bool)s.Attribute("isDynamic") == true select s; } else { filter = from s in xml.Elements("stream") select s; } foreach (XElement e in filter) { AcStream stream = new AcStream(); stream.Name = (string)e.Attribute("name"); stream.ID = (int)e.Attribute("streamNumber"); stream.BasisName = (string)e.Attribute("basis") ?? String.Empty; stream.BasisID = (int?)e.Attribute("basisStreamNumber") ?? -1; stream.Depot = depot; stream.IsDynamic = (bool)e.Attribute("isDynamic"); string type = (string)e.Attribute("type"); stream.Type = (StreamType)Enum.Parse(typeof(StreamType), type); // attribute "time" only exists for snapshot streams (creation date) or when a dynamic stream has a time basis stream.Time = e.acxTime("time"); // time basis stream.StartTime = (DateTime)e.acxTime("startTime"); // hidden attribute exists only if the stream is hidden stream.Hidden = (e.Attribute("hidden") != null); stream.HasDefaultGroup = (bool)e.Attribute("hasDefaultGroup"); lock (_locker) { Add(stream); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcStreams.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcStreams.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcProperty objects for all streams in \e depot or just \e stream in \e depot. /// Optionally include hidden (removed) streams. /// </summary> /// <param name="depot">The depot to query for properties.</param> /// <param name="stream">The stream for a specific stream only, otherwise \e null for all streams in \e depot.</param> /// <param name="includeHidden">\e true to include properties for hidden (removed) streams, \e false otherwise.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c getproperty command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcProperties constructor](@ref AcUtils#AcProperties#AcProperties), initAsync(string, bool) */ /*! \getproperty_ <tt>getproperty \<-fx | -fix\> \<-s \<stream\> | -ks -p \<depot\>\></tt> */ public async Task <bool> initAsync(AcDepot depot, AcStream stream = null, bool includeHidden = false) { bool ret = false; // assume failure try { string cmd = null; if (stream != null && includeHidden) { cmd = $@"getproperty -fix -s ""{stream}"""; } else if (stream != null && !includeHidden) { cmd = $@"getproperty -fx -s ""{stream}"""; } else if (includeHidden) // request is for all streams in depot including those that are hidden { cmd = $@"getproperty -fix -ks -p ""{depot}"""; } else // request is for all streams except those that are hidden { cmd = $@"getproperty -fx -ks -p ""{depot}"""; } AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("property")) { AcProperty property = new AcProperty(); string kind = (string)e.Attribute("kind"); property.Kind = (PropKind)Enum.Parse(typeof(PropKind), kind); property.Depot = depot; property.ID = (int)e.Attribute("streamNumber"); property.Name = (string)e.Attribute("streamName"); property.PropName = (string)e.Attribute("propertyName"); property.PropValue = (string)e; lock (_locker) { Add(property); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcUser objects as per [constructor parameters](@ref AcUtils#AcUsers#AcUsers). /// </summary> /// <param name="progress">Optionally report progress back to the caller.</param> /// <returns>\e true if list initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \show_ <tt>show \<-fx | -fix\> users</tt> */ public async Task <bool> initAsync(IProgress <int> progress = null) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($"show {(_includeDeactivated ? "-fix" : "-fx")} users") .ConfigureAwait(false); if (r != null && r.RetVal == 0) // if command succeeded { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> query = from element in xml.Elements("Element") select element; List <Task <bool> > tasks = new List <Task <bool> >(query.Count()); Func <Task <bool>, bool> cf = t => { bool res = t.Result; if (res && progress != null) { progress.Report(Interlocked.Increment(ref _counter)); } return(res); }; foreach (XElement e in query) { string name = (string)e.Attribute("Name"); int id = (int)e.Attribute("Number"); // XML attribute isActive exists only if the user is inactive, otherwise it isn't there PrinStatus status = (e.Attribute("isActive") == null) ? PrinStatus.Active : PrinStatus.Inactive; AcUser user = new AcUser(id, name, status); lock (_locker) { Add(user); } Task <bool> t = initUserPropsAsync(user).ContinueWith(cf); tasks.Add(t); } bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false); ret = (arr != null && arr.All(n => n == true)); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcUsers.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcUsers.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Initialize this AcDepot object with data from AccuRev as per constructor parameter's depot \e name or \e ID number. /// </summary> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa AcDepot(string, bool, bool), AcDepot(int, bool, bool), [AcDepots constructor](@ref AcUtils#AcDepots#AcDepots) */ /*! \show_ <tt>show -fx depots</tt> */ public async Task <bool> initAsync() { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx depots").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> filter = null; if (_id > 0) { filter = from element in xml.Elements("Element") where (int)element.Attribute("Number") == _id select element; } else { filter = from element in xml.Elements("Element") where (string)element.Attribute("Name") == _name select element; } XElement e = filter.SingleOrDefault(); if (e != null) { ID = (int)e.Attribute("Number"); Name = (string)e.Attribute("Name"); Slice = (int)e.Attribute("Slice"); ExclusiveLocking = (bool)e.Attribute("exclusiveLocking"); string temp = (string)e.Attribute("case"); Case = (CaseSensitivity)Enum.Parse(typeof(CaseSensitivity), temp); _streams = new AcStreams(_dynamicOnly, _includeHidden); ret = await _streams.initAsync(this, listFile()).ConfigureAwait(false); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcDepot.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcDepot.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Determines if the current user is logged into AccuRev and, if so, retrieves their principal name. /// </summary> /// <remarks>Implemented by extracting the user's principal name or string <b>\"(not logged in)\"</b> from the \c info command results.</remarks> /// <returns>A string initialized to the name of the principal logged into AccuRev or \e null if not logged in.</returns> /*! \info_ \c info */ /*! \accunote_ To support GUIs logging into replicas, get host and port from \c info command * (instead of from XML \<serverInfo\> results, which are not correct for replica) * to use in titlebar, preferences.xml, and MQTT messages. 35934/17776122 (35921/17776020) */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c info command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \note The user must have <tt>AccuRev\\bin</tt> in their \e Path environment variable to run * AccuRev commands issued by the AcUtils library. Since this method is often the first function called * by a client application (in this case \c info), a failure here usually means this entry is missing.*/ public static async Task <string> getPrincipalAsync() { string prncpl = null; try { AcResult r = await AcCommand.runAsync("info").ConfigureAwait(false); if (r != null && r.RetVal == 0) { using (StringReader reader = new StringReader(r.CmdResult)) { bool? login = null; // don't know yet string line; char[] sep = new char[] { ':' }; while ((line = reader.ReadLine()) != null && login == null) { string[] arr = line.Split(sep); // "Principal: barnyrd" if (arr.Length == 2) { if (String.Equals(arr[0], "Principal")) { string temp = arr[1].Replace("\t", ""); if (String.Equals(temp, "(not logged in)")) { login = false; } else { prncpl = temp; // AccuRev principal name login = true; } } } } } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getPrincipalAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getPrincipalAsync{Environment.NewLine}{ecx.Message}"); } return(prncpl); // principal name or null if not logged in }
/// <summary> /// Get the depot's stream and workspace (optional) hierarchy relationship data from AccuRev. /// This method is called internally and not by user code. /// </summary> /// <param name="includeWSpaces">\e true to include workspaces in the list.</param> /// <returns>Fully initialized [MultiValueDictionary](https://www.nuget.org/packages/Microsoft.Experimental.Collections) /// object for the depot with [parent(key),children(values)] basis/stream ID's if no exception was thrown /// and the operation succeeded, otherwise \e null on error.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \pre Using \e includeWSpaces to include workspaces in the list requires that all stream types be specified at AcDepot * object creation as per the \e dynamicOnly=false (default) constructor parameter. */ /*! \show_ <tt>show -p \<depot\> [-fix | -fx] -s 1 -r streams</tt> */ /*! \attention This method requires that you deploy * <a href="https://www.nuget.org/packages/Microsoft.Experimental.Collections">Microsoft.Experimental.Collections.dll</a> with your application. */ private async Task <MultiValueDictionary <int, int> > getHierarchyAsync(bool includeWSpaces = false) { MultiValueDictionary <int, int> hierarchy = null; try { AcResult r = await AcCommand.runAsync($@"show -p ""{this}"" {(_includeHidden ? " -fix" : " -fx")} -s 1 -r streams") .ConfigureAwait(false); if (r != null && r.RetVal == 0) // if command succeeded { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> filter; if (includeWSpaces) { filter = from s in xml.Elements("stream") select s; } else { filter = from s in xml.Elements("stream") where (string)s.Attribute("type") != "workspace" // all except workspaces select s; } int capacity = filter.Count(); hierarchy = new MultiValueDictionary <int, int>(capacity); foreach (XElement e in filter) { // XML attribute basisStreamNumber does not exist in the case of root streams int parent = (int?)e.Attribute("basisStreamNumber") ?? -1; int child = (int)e.Attribute("streamNumber"); hierarchy.Add(parent, child); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcDepot.getHierarchyAsync{Environment.NewLine}{ecx.Message}"); hierarchy = null; } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcDepot.getHierarchyAsync{Environment.NewLine}{ecx.Message}"); hierarchy = null; } return(hierarchy); }
/// <summary> /// Retrieves the AccuRev program major, minor and patch version numbers. /// </summary> /// <returns>An array initialized as <em>int[]={major, minor, patch}</em> on success, otherwise \e null on error.</returns> /*! \xml_ <tt>xml -l \<xmlfile\></tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c xml command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \code * <?xml version="1.0" encoding="utf-8"?> * <serverInfo> * <serverVersion * major="5" * minor="6" * patch="0"/> * <serverHostPort>machine_name_omitted:5050</serverHostPort> * </serverInfo> * \endcode */ public static async Task <int[]> getAccuRevVersionAsync() { int[] arr = null; // major, minor, patch string tempFile = null; try { tempFile = Path.GetTempFileName(); // the AccuRev xml command requires a file as its argument using (StreamWriter streamWriter = new StreamWriter(tempFile)) { streamWriter.Write(@"<serverInfo/>"); // set up the query } AcResult r = await AcCommand.runAsync($@"xml -l ""{tempFile}""").ConfigureAwait(false); if (r != null && r.RetVal == 0) { using (StringReader reader = new StringReader(r.CmdResult)) { XElement doc = XElement.Load(reader); XElement sv = doc.Element("serverVersion"); int major = (int)sv.Attribute("major"); int minor = (int)sv.Attribute("minor"); int patch = (int)sv.Attribute("patch"); arr = new int[] { major, minor, patch }; } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getAccuRevVersionAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getAccuRevVersionAsync{Environment.NewLine}{ecx.Message}"); } finally { if (tempFile != null) { File.Delete(tempFile); } } return(arr); }
/// <summary> /// Put a \c lock on \e stream as per lock \e kind. /// </summary> /// <param name="stream">Name of stream or workspace to lock.</param> /// <param name="comment">Comment to be used for the lock.</param> /// <param name="kind">Type of lock to apply: \e to, \e from, or \e all.</param> /// <param name="prncpl">AccuRev principal name of user or group in the case of \e to or \e from lock.</param> /// <param name="onlyexcept">Apply \c lock to \e prncpl only or to all except \e prncpl.</param> /// <returns>\e true if operation succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c lock command failure.</exception> /*! \lock_ <tt>lock -c \<comment\> [-kf [-e|-o prncpl] | -kt [-e|-o prncpl]] \<stream\></tt> */ /*! \accunote_ The CLI \c lock command can be used on a workspace stream but the same cannot be done using the AccuRev GUI client. AccuRev defect 23850. */ public async Task <bool> lockAsync(string stream, string comment, LockKind kind = LockKind.all, AcPrincipal prncpl = null, OnlyExcept onlyexcept = OnlyExcept.Except) { bool ret = false; // assume failure try { string cmd = null; if (kind == LockKind.from) { if (prncpl != null) { cmd = $@"lock -c ""{comment}"" -kf {((onlyexcept == OnlyExcept.Except) ? "-e" : "-o")} ""{prncpl}"" ""{stream}"""; } else { cmd = $@"lock -c ""{comment}"" -kf ""{stream}"""; // lock 'from' for all } } else if (kind == LockKind.to) { if (prncpl != null) { cmd = $@"lock -c ""{comment}"" -kt {((onlyexcept == OnlyExcept.Except) ? "-e" : "-o")} ""{prncpl}"" ""{stream}"""; } else { cmd = $@"lock -c ""{comment}"" -kt ""{stream}"""; // lock 'to' for all } } else if (kind == LockKind.all) { cmd = $@"lock -c ""{comment}"" ""{stream}"""; // lock 'to and from' for all } AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false); ret = (r != null && r.RetVal == 0); } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException in AcLocks.lockAsync caught and logged.{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcLock objects on streams in \e depots. /// </summary> /// <param name="depots">Limit the list of locks to those on streams in \e depots only. Depot names in \e depots /// must match their respective AccuRev depot name exactly.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcLocks constructor](@ref AcUtils#AcLocks#AcLocks), initAsync(AcDepot), initAsync(StreamsCollection) */ /*! \show_ <tt>show -fx locks</tt> */ public async Task <bool> initAsync(DepotsCollection depots) { AcDepots dlist = new AcDepots(); if (!(await dlist.initAsync(depots).ConfigureAwait(false))) { return(false); } bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx locks").ConfigureAwait(false); if (r != null && r.RetVal == 0) { bool result = true; XElement xml = XElement.Parse(r.CmdResult); for (int ii = 0; ii < dlist.Count && result; ii++) { AcDepot depot = dlist[ii]; IEnumerable <XElement> query = from e in xml.Elements("Element") join AcStream s in depot.Streams on(string) e.Attribute("Name") equals s.Name select e; result = initList(query); } ret = result; } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcLocks.initAsync(DepotsCollection){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcLocks.initAsync(DepotsCollection){Environment.NewLine}{ecx.Message}"); } return(ret); }
//@} #endregion /// <summary> /// Get the list of workspaces in XML for all or the current user and optionally include /// inactive workspaces as per [AcWorkspaces constructor](@ref AcUtils#AcWorkspaces#AcWorkspaces) \e includeHidden parameter. /// </summary> /// <returns>AcResult initialized with the \c show command results, otherwise \e null on error.</returns> /*! \show_ <tt>show \<-fvx | -fvix\> \<-a | \> wspaces</tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on <tt>show wspaces</tt> command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa AcWorkspaces.getReferenceTreesXMLAsync */ private async Task <AcResult> getWorkspacesXMLAsync() { AcResult result = null; try { string cmd = null; // for all below, -v option adds the Loc (location) to output if (_allWSpaces && _includeHidden) { // All workspaces, not just those that belong to the principal. Include deactivated workspaces. cmd = "show -fvix -a wspaces"; // -a is the only option available for show wspaces } else if (_allWSpaces && !_includeHidden) { // All workspaces, not just those that belong to the principal. Do not include deactivated workspaces. cmd = "show -fvx -a wspaces"; } else if (!_allWSpaces && _includeHidden) { // Only those workspaces that belong to the principal. Include deactivated workspaces. cmd = "show -fvix wspaces"; } else if (!_allWSpaces && !_includeHidden) { // Only those workspaces that belong to the principal. Do not include deactivated workspaces. cmd = "show -fvx wspaces"; } result = await AcCommand.runAsync(cmd).ConfigureAwait(false); } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcWorkspaces.getWorkspacesXMLAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcWorkspaces.getWorkspacesXMLAsync{Environment.NewLine}{ecx.Message}"); } return(result); }
/// <summary> /// Populate this container with AcSession objects, the currently active login sessions. /// </summary> /// <returns>\e true if no failure occurred and list was initialized successfully, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \show_ <tt>show -fx sessions</tt> */ public async Task <bool> initAsync() { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx sessions").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("Element")) { AcSession session = new AcSession(); session.Name = (string)e.Attribute("Username"); session.Host = (string)e.Attribute("Host"); string temp = (string)e.Attribute("Duration"); if (!String.Equals(temp, "(timed out)")) { double duration = double.Parse(temp); session.Duration = TimeSpan.FromMinutes(duration); } lock (_locker) { Add(session); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcSessions.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcSessions.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcRule objects for \e stream as per /// [constructor parameter](@ref AcUtils#AcRules#AcRules) \e explicitOnly. /// </summary> /// <param name="stream">The stream to query for rules.</param> /// <returns>\e true if no failure occurred and list was initialized successfully, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c lsrules command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \lsrules_ <tt>lsrules -s \<stream\> [-d] -fx</tt> */ /*! \code * <!-- accurev lsrules -s "PG_DEV1" -fx --> * <AcResponse * Command="lscomp" * TaskId="54394"> * <element * kind="incl" * elemType="dir" * dir="yes" // Not used as its redundant. We use ElementType.Dir instead. * location="\.\Iconic" * setInStream="PG_DEV1" * xlinkToStream="IC_DEV1" * options="1"/> // Obsolete. Was used for compatibility of rules in version 4.5.3 and earlier. Will always be a value of 1. * <element * kind="incl" * elemType="dir" * dir="yes" * location="\.\" * setInStream="PlayGround" * options="1"/> * </AcResponse> * \endcode */ public async Task <bool> initAsync(AcStream stream) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"lsrules -s ""{stream}"" {(_explicitOnly ? "-d" : String.Empty)} -fx") .ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("element")) { AcRule rule = new AcRule(); string kind = (string)e.Attribute("kind"); rule.Kind = (RuleKind)Enum.Parse(typeof(RuleKind), kind); string type = (string)e.Attribute("elemType"); rule.Type = (ElementType)Enum.Parse(typeof(ElementType), type); rule.Location = (string)e.Attribute("location"); rule.SetInStream = (string)e.Attribute("setInStream"); rule.XlinkToStream = (string)e.Attribute("xlinkToStream") ?? String.Empty; lock (_locker) { Add(rule); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcRules.initAsync(AcStream){Environment.NewLine}{ecx.Message}"); } return(ret); }
//@} #endregion /// <summary> /// Optionally called during [list construction](@ref AcUtils#AcGroups#AcGroups) to initialize the /// [list of principals](@ref AcPrincipal#Members) (users and groups) that are direct (explicit) members of \e group. /// This method is called internally and not by user code. /// </summary> /// <remarks>Membership lists for inactive groups are empty (not initialized). An inactive group's membership list will /// reappear when the group is reactivated.</remarks> /// <param name="group">Name of AccuRev group.</param> /// <returns>\e true if no exception was thrown and operation succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcUser.initGroupsListAsync](@ref AcUtils#AcUser#initGroupsListAsync) */ /*! \show_ <tt>show -fx -g \<group\> members</tt> */ /*! \accunote_ Unlike the \c show command used here, its <tt>show -fx -u \<user\> groups</tt> counterpart * does include memberships resulting from indirect (implicit) membership. */ private async Task <bool> initMembersListAsync(string group) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"show -fx -g ""{group}"" members").ConfigureAwait(false); if (r != null && r.RetVal == 0) // if command succeeded { SortedSet <string> members = new SortedSet <string>(); XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("Element")) { string name = (string)e.Attribute("User"); members.Add(name); } lock (_locker) { AcPrincipal prncpl = getPrincipal(group); prncpl.Members = members; } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcGroups.initMembersListAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcGroups.initMembersListAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcPermission objects. /// </summary> /// <param name="name">Optional depot or stream name as per /// [constructor parameter](@ref AcUtils#AcPermissions#AcPermissions) \e kind, otherwise all.</param> /// <returns>\e true if no failure occurred and list was initialized successfully, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c lsacl command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcPermissions constructor](@ref AcUtils#AcPermissions#AcPermissions) */ /*! \lsacl_ <tt>lsacl -fx {stream|depot} \<name\></tt> */ public async Task <bool> initAsync(string name = null) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"lsacl -fx {_kind} ""{name}""").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("Element")) { AcPermission perm = new AcPermission(_kind); perm.Name = (string)e.Attribute("Name"); perm.AppliesTo = (string)e.Attribute("Group"); string type = (string)e.Attribute("Type"); perm.Type = (PermType)Enum.Parse(typeof(PermType), type); string rights = (string)e.Attribute("Rights"); perm.Rights = (PermRights)Enum.Parse(typeof(PermRights), rights); perm.Inheritable = (bool)e.Attribute("Inheritable"); lock (_locker) { Add(perm); } } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcPermissions.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcPermissions.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// For the real version specified in the argument list, get the real stream/version /// for the version in the specified version's workspace backing stream. /// </summary> /// <remarks>\c diff used here with the \c -i option, not to run a diff but to get the EID's only.</remarks> /// <param name="realverspec">Real version specification in text format, /// for example <tt>PG_MAINT1_barnyrd\4</tt> (numeric format won't work).</param> /// <param name="depot">The depot.</param> /// <param name="depotrelpath">Depot relative path, for example <tt>\\\\\.\\Bin\\foo.java</tt></param> /// <returns>An array initialized as <em>int[]={realStreamNumber, realVersionNumber}</em> if available, otherwise \e null.</returns> /*! \diff_ The \c diff command returns <em>zero (0)</em> for no differences found, * <em>one (1)</em> for differences found, or <em>two (2)</em> on \c diff program error.<br> * <tt>diff -fx -v \<realverspec\> -b -i -p \<depot\> \<depotrelpath\></tt> */ /*! > -v -b Compare the specified version (X) with the version in X's stream's backing stream. (Use -v -V instead if comparing elements of type text that are active in a time-based stream.) */ /*! > -i Information only: Report the IDs of the two versions, but don't actually compare them. This option is valid only in a command that uses a -v/-V combination or a -v/-b combination. If an element appears only in the workspace stream, not in the workspace's backing stream, this option does not list it. */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c diff command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> public static async Task <int[]> getBackedVersionAsync(string realverspec, AcDepot depot, string depotrelpath) { int[] arr = null; // {realStreamNumber, realVersionNumber} try { AcResult r = await AcCommand.runAsync($@"diff -fx -v ""{realverspec}"" -b -i -p ""{depot}"" ""{depotrelpath}""") .ConfigureAwait(false); if (r != null && r.RetVal < 2) { XElement xml = XElement.Parse(r.CmdResult); XElement stream2 = xml.Descendants().Where(n => n.Name == "Stream2").SingleOrDefault(); if (stream2 != null) { XAttribute version = stream2.Attributes("Version").SingleOrDefault(); if (version != null) { string temp = (string)version; string[] a = temp.Split('/'); int realStreamNumber = Int32.Parse(a[0], NumberStyles.Integer); int realVersionNumber = Int32.Parse(a[1], NumberStyles.Integer); arr = new int[] { realStreamNumber, realVersionNumber }; } } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcQuery.getBackedVersionAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcQuery.getBackedVersionAsync{Environment.NewLine}{ecx.Message}"); } return(arr); }
/// <summary> /// Populate this container with AcLock objects on streams in \e depot or all AcLock objects in the repository. /// </summary> /// <param name="depot">Limit the list of locks to those on \e depot only, otherwise /// \e null for all locks in the repository.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcLocks constructor](@ref AcUtils#AcLocks#AcLocks), initAsync(DepotsCollection), initAsync(StreamsCollection) */ /*! \show_ <tt>show -fx locks</tt> */ public async Task <bool> initAsync(AcDepot depot = null) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx locks").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> query = null; if (depot == null) { query = from e in xml.Elements("Element") select e; } else { query = from e in xml.Elements("Element") join AcStream s in depot.Streams on(string) e.Attribute("Name") equals s.Name select e; } ret = initList(query); } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcLocks.initAsync(AcDepot){Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcLocks.initAsync(AcDepot){Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Get the list of reference trees in XML and optionally include those that are inactive /// as per [AcWorkspaces constructor](@ref AcUtils#AcWorkspaces#AcWorkspaces) \e includeHidden parameter. /// </summary> /// <returns>AcResult initialized with the \c show command results, or \e null on error.</returns> /*! \show_ <tt>show \<-fvx | -fvix\> refs</tt> */ /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on <tt>show refs</tt> command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa AcWorkspaces.getWorkspacesXMLAsync */ private async Task <AcResult> getReferenceTreesXMLAsync() { AcResult result = null; try { // -fvix: display all reference trees including deactivated ones // -fvx: display only active reference trees result = await AcCommand.runAsync($"show {(_includeHidden ? "-fvix" : "-fvx")} refs").ConfigureAwait(false); } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcWorkspaces.getReferenceTreesXMLAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcWorkspaces.getReferenceTreesXMLAsync{Environment.NewLine}{ecx.Message}"); } return(result); }
/// <summary> /// Optionally called during [list construction](@ref AcUtils#AcUsers#AcUsers) to initialize the list of groups /// this user is a member of by way of direct or indirect (implicit) membership, e.g. Mary is implicitly a member /// of groupA because she's a member of groupB which is a member of groupA. This method is called internally /// and not by user code. /// </summary> /// <remarks>Membership lists for inactive users are initialized too when /// [constructor parameter](@ref AcUtils#AcUsers#AcUsers) \e includeDeactivated is \e true.</remarks> /// <returns>\e true if no exception was thrown and operation succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) /// in <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \sa [AcGroups.initMembersListAsync](@ref AcUtils#AcGroups#initMembersListAsync) */ /*! \show_ <tt>show -fx -u \<user\> groups</tt> */ /*! \accunote_ Unlike the \c show command used here, its <tt>show -fx -g \<group\> members</tt> counterpart * does not include memberships resulting from indirect (implicit) membership. */ internal async Task <bool> initGroupsListAsync() { bool ret = false; // assume failure try { // works for inactive users too AcResult r = await AcCommand.runAsync($@"show -fx -u ""{Principal.Name}"" groups") .ConfigureAwait(false); if (r != null && r.RetVal == 0) // if command succeeded { SortedSet <string> members = new SortedSet <string>(); XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("Element")) { string name = (string)e.Attribute("Name"); members.Add(name); } Principal.Members = members; ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcUser.initGroupsListAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcUser.initGroupsListAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcDepot objects as per [constructor parameters](@ref AcUtils#AcDepots#AcDepots). /// </summary> /// <param name="depotsCol">List of depots to create, otherwise \e null for all depots.</param> /// <param name="progress">Optionally report progress back to the caller.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \code * DepotsSection ds = ConfigurationManager.GetSection("Depots") as DepotsSection; * DepotsCollection _dcol = ds.Depots; // list of depots from FooApp.exe.config * ... * private async Task<bool> initComboBoxDepotsAsync() * { * bool ret = false; // assume failure * try * { * toolStripStatusLabel.Text = "Initializing..."; * toolStripProgressBar.Visible = true; * toolStripProgressBar.Maximum = _dcol.Count; * Progress<int> progress = new Progress<int>(i => toolStripProgressBar.Value = i); * * AcDepots depots = new AcDepots(dynamicOnly: true); * if (await depots.initAsync(_dcol, progress)) // if initialization succeeds * { * foreach (AcDepot depot in depots) * toolStripComboBoxDepot.Items.Add(depot); // a ToolStripComboBox control * ret = true; // operation succeeded * } * else * { * AcDebug.Log("Failure in FooApp.initComboBoxDepotsAsync"); * MessageBox.Show($"Depots list initialization failed. See log file:{Environment.NewLine}{AcDebug.getLogFile()}", * "FooApp", MessageBoxButtons.OK, MessageBoxIcon.Hand); * } * } * * catch (Exception ecx) * { * AcDebug.Log($"Exception caught and logged in FooApp.initComboBoxDepotsAsync{Environment.NewLine}{ecx.Message}"); * } * * finally * { * toolStripStatusLabel.Text = "Ready"; * toolStripProgressBar.Visible = false; * } * * return ret; * } * \endcode */ /*! \sa [AcDepots constructor](@ref AcUtils#AcDepots#AcDepots), DepotsCollection, AcGroups.initAsync */ /*! \show_ <tt>show -fx depots</tt> */ /*! \accunote_ The XML attribute \e locWidth from <tt>show -fx depots</tt> is obsolete. * It's an AccuRev 4.x artifact and should be removed. RPI defect 1112042, SupportLine AR3325. */ public async Task <bool> initAsync(DepotsCollection depotsCol = null, IProgress <int> progress = null) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync("show -fx depots").ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> query = null; if (depotsCol == null) { query = from e in xml.Elements("Element") select e; } else { query = from e in xml.Elements("Element") where depotsCol.OfType <DepotElement>().Any(de => de.Depot == (string)e.Attribute("Name")) select e; } int num = query.Count(); List <Task <bool> > tasks = new List <Task <bool> >(num); Func <Task <bool>, bool> cf = t => { bool res = t.Result; if (res && progress != null) { progress.Report(Interlocked.Increment(ref _counter)); } return(res); }; foreach (XElement e in query) { AcDepot depot = new AcDepot(_dynamicOnly, _includeHidden); depot.ID = (int)e.Attribute("Number"); depot.Name = (string)e.Attribute("Name"); depot.Slice = (int)e.Attribute("Slice"); depot.ExclusiveLocking = (bool)e.Attribute("exclusiveLocking"); string temp = (string)e.Attribute("case"); depot.Case = (CaseSensitivity)Enum.Parse(typeof(CaseSensitivity), temp); depot._streams = new AcStreams(_dynamicOnly, _includeHidden); lock (_locker) { Add(depot); } Task <bool> t = depot._streams.initAsync(depot, depot.listFile()).ContinueWith(cf); tasks.Add(t); } bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false); ret = (arr != null && arr.All(n => n == true)); // true if all succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcDepots.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcDepots.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
/// <summary> /// Populate this container with AcPrincipal objects as per [constructor parameters](@ref AcUtils#AcGroups#AcGroups). /// </summary> /// <param name="progress">Optionally report progress back to the caller when group membership initialization /// is requested as per [constructor parameter](@ref AcUtils#AcGroups#AcGroups) \e includeMembersList.</param> /// <returns>\e true if initialization succeeded, \e false otherwise.</returns> /// <exception cref="AcUtilsException">caught and [logged](@ref AcUtils#AcDebug#initAcLogging) in /// <tt>\%LOCALAPPDATA\%\\AcTools\\Logs\\<prog_name\>-YYYY-MM-DD.log</tt> on \c show command failure.</exception> /// <exception cref="Exception">caught and logged in same on failure to handle a range of exceptions.</exception> /*! \show_ <tt>show \<-fx | -fix\> groups</tt> */ public async Task <bool> initAsync(IProgress <int> progress = null) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($"show {(_includeDeactivated ? "-fix" : "-fx")} groups") .ConfigureAwait(false); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); IEnumerable <XElement> query = from element in xml.Elements("Element") select element; List <Task <bool> > tasks = null; if (_includeMembersList) { int num = query.Count(); tasks = new List <Task <bool> >(num); } Func <Task <bool>, bool> cf = t => { bool res = t.Result; if (res && progress != null) { progress.Report(Interlocked.Increment(ref _counter)); } return(res); }; foreach (XElement e in query) { AcPrincipal group = new AcPrincipal(); group.Name = (string)e.Attribute("Name"); group.ID = (int)e.Attribute("Number"); // XML attribute isActive exists only if the group is inactive, otherwise it isn't there group.Status = (e.Attribute("isActive") == null) ? PrinStatus.Active : PrinStatus.Inactive; lock (_locker) { Add(group); } if (_includeMembersList) { Task <bool> t = initMembersListAsync(group.Name).ContinueWith(cf); tasks.Add(t); } } if (!_includeMembersList) { ret = true; // list initialization succeeded } else // run membership initialization in parallel { bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(false); ret = (arr != null && arr.All(n => n == true)); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in AcGroups.initAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in AcGroups.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }