// Returns the attributes for the element in stream if the query succeeded, otherwise null. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on stat command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <XElement> getElementInfoAsync(AcStream stream, string element) { XElement e = null; try { AcResult r = await AcCommand.runAsync($@"stat -fx -s ""{stream}"" ""{element}"""); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); e = xml.Element("element"); e.AddAnnotation(stream); // add stream since it's not in the XML } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.getElementInfoAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.getElementInfoAsync{Environment.NewLine}{ecx.Message}"); } return(e); }
// Returns one (1) on program failure or no elements found to move, zero (0) on success. static int Main(string[] args) { bool ret = false; // assume failure if (args.Length != 1) { Console.WriteLine(@"Example usage: C:\Workspaces\MARS_DEV2\Foo>moveto ..\Bar"); return 1; } if (!init()) return 1; // program startup initialization string destfolder = args[0]; string tempfile; if (store(destfolder, out tempfile)) // get elements to be moved { if (ready(destfolder)) // ensure folder exists and is in AccuRev { try { AcResult r = AcCommand.run($@"move -l ""{tempfile}"" ""{destfolder}"""); ret = (r.RetVal == 0); } catch (AcUtilsException ecx) { Console.WriteLine($"AcUtilsException caught in Program.Main{Environment.NewLine}{ecx.Message}"); } } } if (tempfile != null) File.Delete(tempfile); return ret ? 0 : 1; }
// Run the AccuRev stat command for the stream and initialize our _map class variable with the results. // Returns true if the operation succeeded, false otherwise. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\Stranded-YYYY-MM-DD.log on stat command failure. Exception caught and // logged in same for a range of exceptions. private static async Task <bool> runStatCommandAsync(AcStream stream) { bool ret = false; // assume failure try { AcResult result = await AcCommand.runAsync($@"stat -fx -s ""{stream}"" -i"); if (result != null && result.RetVal == 0) { XElement xml = XElement.Parse(result.CmdResult); int num = xml.Elements("element").Count(); if (num > 0) { lock (_locker) { _map.Add(stream, initVal(xml)); } } } ret = true; } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.runStatCommandAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.runStatCommandAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
public static RibbonButton AddButton(this RibbonItemCollection items, AcCommand command) { RibbonButton btn = new RibbonButton(); items.AddItem(btn, command); return(btn); }
public string TurnOff() { var cmd = new AcCommand().TurnOff(); _ac.Execute(cmd); return("ok"); }
// Get the latest transaction in the depot that occurred the last time wspace was successfully updated, // otherwise returns null on error. Adds wspace to the transaction as an annotation. AcUtilsException // caught and logged in %LOCALAPPDATA%\AcTools\Logs\WSpaceTransLevel-YYYY-MM-DD.log on hist command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <XElement> latestTransAsync(AcWorkspace wspace) { XElement trans = null; // assume failure try { AcResult r = await AcCommand.runAsync($@"hist -fx -p ""{wspace.Depot}"" -t {wspace.UpdateLevel}"); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); trans = xml.Element("transaction"); if (trans != null) { trans.AddAnnotation(wspace); } } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.latestTransAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.latestTransAsync{Environment.NewLine}{ecx.Message}"); } return(trans); }
// Run the hist command for depot and add the results to our transactions list. Returns // true if operation succeeds, otherwise false. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\LatestTransactions-YYYY-MM-DD.log on hist command failure. // Exception caught and logged in same for a range of exceptions. private async static Task <bool> initLastTransAsync(string depot) { bool ret = false; // assume failure try { AcResult r = await AcCommand.runAsync($@"hist -p ""{depot}"" -t now -fx"); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); XElement trans = xml.Element("transaction"); trans.AddAnnotation(depot); // add depot since it's not in the XML lock (_locker) { _transactions.Add(trans); } ret = true; } } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initLastTransAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initLastTransAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Run the show triggers command for depot and add the results to our list. Returns true // if the operation succeeded, false otherwise. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\Triggers-YYYY-MM-DD.log on show command failure. // Exception caught and logged in same for a range of exceptions. private async Task <bool> initListAsync(string depot) { bool ret = false; // assume failure try { AcResult result = await AcCommand.runAsync($@"show -p ""{depot}"" -fx triggers"); if (result != null && result.RetVal == 0) { XElement xml = XElement.Parse(result.CmdResult); xml.AddAnnotation(depot); // add depot since it's not in the XML lock (_locker) { Add(xml); } ret = true; } } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initListAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initListAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Initialize our dictionary class variable with [element, EID] for all elements in all dynamic streams in depot. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on stat command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <bool> initMapAsync(AcDepot depot) { bool ret = false; // assume failure try { IEnumerable <AcStream> filter = from n in depot.Streams where n.IsDynamic && !n.Hidden select n; List <Task <AcResult> > tasks = new List <Task <AcResult> >(filter.Count()); foreach (AcStream stream in filter) { tasks.Add(AcCommand.runAsync($@"stat -a -s ""{stream}"" -fx")); // -a for all elements in stream } AcResult[] arr = await Task.WhenAll(tasks); // finish running stat commands in parallel if (arr != null && arr.All(n => n.RetVal == 0)) // true if all initialized successfully { HashSet <Tuple <string, int> > hset = new HashSet <Tuple <string, int> >(_tcompare); foreach (AcResult r in arr) { // if empty the stream has an ACL that is preventing us from reading it or some other error occurred if (r == null || String.IsNullOrEmpty(r.CmdResult)) { continue; } XElement xml = XElement.Parse(r.CmdResult); foreach (XElement e in xml.Elements("element")) { string path = (string)e.Attribute("location"); int eid = (int)e.Attribute("id"); hset.Add(new Tuple <string, int>(path, eid)); } } lock (_locker) { _map.Add(depot, hset); } ret = true; // operation succeeded } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.initMapAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initMapAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Run the stat command for all dynamic streams in depot and initialize our dictionary class variable // with the xlinked elements found that have a type listed in ElementTypes from XLinked.exe.config. // Returns true if the operation succeeded, false otherwise. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\XLinked-YYYY-MM-DD.log on stat command failure. Exception caught and // logged in same for a range of exceptions. private static async Task <bool> initAsync(AcDepot depot) { bool ret = false; // assume failure try { int num = depot.Streams.Count(); List <Task <AcResult> > tasks = new List <Task <AcResult> >(num); foreach (AcStream stream in depot.Streams) { // -k: Display the element type (that is, data type) of this version // -v: Display the target of an element link or symbolic link tasks.Add(AcCommand.runAsync($@"stat -s ""{stream}"" -a -fkvx")); } HashSet <XElement> hset = new HashSet <XElement>(_comparer); while (tasks.Count > 0) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); foreach (XElement e in xml.Elements("element") // attribute xlinked="true" exists only when status includes (xlinked), // otherwise it isn't there (i.e. there never is an xlinked="false" in the XML) .Where(n => (string)n.Attribute("xlinked") != null && _etypes.Any(t => t == n.acxType("elemType")))) { hset.Add(e); } } lock (_locker) { _map.Add(depot, hset); } ret = true; } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Run the stat command for streams in depots listed in LatestOverlaps.exe.config and add the // results to the Stat.Elements list. Returns true if initialization succeeded, false otherwise. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestOverlaps-YYYY-MM-DD.log // on stat command failure. Exception caught and logged in same for a range of exceptions. private static async Task <bool> initStatAsync() { bool ret = false; // assume failure try { IEnumerable <XElement> trans = from e in _hist.Elements("transaction") select e; ILookup <string, XElement> map = trans.ToLookup(n => (string)n.Attribute("streamName"), n => n); List <Task <AcResult> > tasks = new List <Task <AcResult> >(); foreach (var ii in map) // for each stream { AcStream stream = _depots.getStream(ii.Key); if (!stream.HasDefaultGroup) { continue; // run stat only if default group exists } tasks.Add(AcCommand.runAsync($@"stat -s ""{stream}"" -o -fx")); } bool op = true; while (tasks.Count > 0 && op) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); op = (r != null && r.Result.RetVal == 0 && Stat.init(r.Result.CmdResult)); } ret = op; // true if all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initStatAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initStatAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Helper function that runs our stat commands. private static async Task <bool> runStatCommandAsync(string cmd) { bool ret = false; // assume failure AcResult result = null; try { result = await AcCommand.runAsync(cmd); ret = (result != null && result.RetVal == 0); } catch (AcUtilsException exc) { Console.WriteLine($"AcUtilsException caught in runStatCommandAsync{Environment.NewLine}{exc.Message}"); } return(ret && Stat.init(result.CmdResult)); }
// Run the hist command for depots listed in LatestOverlaps.exe.config and add the results to // our history list class variable. Returns true if initialization succeeded, false otherwise. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestOverlaps-YYYY-MM-DD.log // on hist command failure. Exception caught and logged in same for a range of exceptions. private static async Task <bool> initHistAsync(DateTime past) { bool ret = false; // assume failure try { string timeHrsAgo = AcDateTime.DateTime2AcDate(past); // get date in string format suitable for AccuRev CLI List <Task <AcResult> > tasks = new List <Task <AcResult> >(_depots.Count); foreach (AcDepot depot in _depots) { tasks.Add(AcCommand.runAsync($@"hist -k promote -p ""{depot}"" -t now-""{timeHrsAgo}"" -fex")); } _hist = new List <XElement>(_depots.Count); while (tasks.Count > 0) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); _hist.Add(xml); } ret = true; // if we're here then all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initHistAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initHistAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
public string SetStatus(int temp, int fanPerc, string mode) { var cmd = new AcCommand() .SetTemperature(temp) .SetFanSpeed(_ac, (byte)fanPerc); if (!string.IsNullOrEmpty(mode)) { if (mode == "cold") { cmd.Cold(); } if (mode == "heat") { cmd.Heat(); } } _ac.Execute(cmd); return("ok"); }
// Determines whether the user's default directory is located somewhere in the current workspace tree. // Returns true if the operation succeeded, false otherwise. private static bool isCurrDirInWSpace() { bool found = false; // assume no workspace found try { AcResult r = AcCommand.run("info"); if (r.RetVal == 0) { using (StringReader sr = new StringReader(r.CmdResult)) { string line; char[] sep = new char[] { ':' }; while ((line = sr.ReadLine()) != null) { string[] arr = line.Split(sep); // "Workspace/ref: MARS_DEV2_barnyrd" if (arr.Length == 2) { if (String.Equals(arr[0], "Workspace/ref")) { found = true; break; } } } } } } catch (AcUtilsException ecx) { Console.WriteLine($"AcUtilsException caught in Program.isCurrDirInWSpace{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { Console.WriteLine($"Exception caught in Program.isCurrDirInWSpace{Environment.NewLine}{ecx.Message}"); } return found; }
// Store the list of elements for the move operation in a temp file. // Returns true if the operation succeeded, otherwise false on error or if no elements found. private static bool store(string destfolder, out string tempfile) { tempfile = null; bool ret = false; // assume failure try { AcResult r = AcCommand.run("stat -fax *"); // the current directory if (r.RetVal == 0) // if command succeeded { string fullpath = Path.GetFullPath(destfolder); // in case the relative path was given XElement xml = XElement.Parse(r.CmdResult); IEnumerable<XElement> filter = from e in xml.Elements("element") where !_skipOver.Any(s => e.Attribute("status").Value.Contains(s)) && // avoid: "You cannot move an element into itself." !fullpath.Equals((string)e.Attribute("location"), StringComparison.OrdinalIgnoreCase) select e; tempfile = Path.GetTempFileName(); using (StreamWriter sw = new StreamWriter(tempfile)) { foreach (XElement e in filter) sw.WriteLine((string)e.Attribute("location")); } FileInfo fi = new FileInfo(tempfile); ret = fi.Length > 0; } } catch (AcUtilsException ecx) { Console.WriteLine($"AcUtilsException caught in Program.store{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { Console.WriteLine($"Exception caught in Program.store{Environment.NewLine}{ecx.Message}"); } return ret; }
// Ensure that the destination folder exists and is in AccuRev. // Returns true if the operation succeeded, false on error. private static bool ready(string dest) { bool ret = false; // assume failure try { if (!Directory.Exists(dest)) { Directory.CreateDirectory(dest); AcCommand.run($@"add ""{dest}"""); } else { AcResult r = AcCommand.run($@"stat -fx ""{dest}"""); if (r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); string status = (string)xml.Element("element").Attribute("status"); if (status == "(external)") AcCommand.run($@"add ""{dest}"""); } } ret = true; } catch (AcUtilsException ecx) { Console.WriteLine($"AcUtilsException caught in Program.ready{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { Console.WriteLine($"Exception caught in Program.ready{Environment.NewLine}{ecx.Message}"); } return ret; }
public static void AddItem(this RibbonItemCollection items, RibbonCommandItem item, AcCommand command) { item.Description = command.Description; AddItem(items, item, command.DisplayName, command, command.SmallImage, command.LargeImage); }
// Initialize our history and stat lists for each stream listed in the LatestPromotions.exe.config Streams section. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestPromotions-YYYY-MM-DD.log on hist or stat // command failure. Exception caught and logged in same on failure to handle a range of exceptions. private static async Task <bool> initListsAsync(DateTime past) { bool ret = false; // assume failure try { string timeHrsAgo = AcDateTime.DateTime2AcDate(past); // get date in string format suitable for AccuRev CLI List <Task <AcResult> >[] tasks = new List <Task <AcResult> > [2]; tasks[0] = new List <Task <AcResult> >(); // for hist results tasks[1] = new List <Task <AcResult> >(); // for stat results // Alternatively change Equals() to Contains() and modify LatestPromotions.exe.config stream values // accordingly to filter on stream name subsets, e.g. <add stream="DEV"/> for all streams with DEV in their name. foreach (AcStream stream in _depots.SelectMany(d => d.Streams .Where(s => _selStreams.OfType <StreamElement>().Any(se => s.Name.Equals(se.Stream))))) { Task <AcResult> hr = AcCommand.runAsync($@"hist -k promote -s ""{stream}"" -t now-""{timeHrsAgo}"" -fx"); tasks[0].Add(hr); Task <AcResult> sr = AcCommand.runAsync($@"stat -s ""{stream}"" -d -fx"); // stream's default group tasks[1].Add(sr); } _hist = new List <XElement>(tasks[0].Count); while (tasks[0].Count > 0) // process hist results { Task <AcResult> r = await Task.WhenAny(tasks[0]); tasks[0].Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } XElement xml = XElement.Parse(r.Result.CmdResult); _hist.Add(xml); } while (tasks[1].Count > 0) // process stat results { Task <AcResult> r = await Task.WhenAny(tasks[1]); tasks[1].Remove(r); if (r == null || r.Result.RetVal != 0) { return(false); } if (!Stat.init(r.Result.CmdResult)) { return(false); } } ret = true; // if we're here then all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initListsAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initListsAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
private static async Task <bool> fileHistAsync(string depot, int eid, string startTime, string endTime) { Console.WriteLine($@"Depot: {depot}, EID: {eid} ""{startTime} - {endTime}""{Environment.NewLine}"); string time = $"{endTime} - {startTime}"; // reverse start-end times as workaround for AccuRev issue 15780 AcResult result = await AcCommand.runAsync($@"hist -p ""{depot}"" -t ""{time}"" -e {eid} -fevx"); if (result == null || result.RetVal != 0) { return(false); // operation failed, check log file } XElement xml = XElement.Parse(result.CmdResult); XElement e = xml.Element("element"); foreach (XElement t in e.Elements("transaction")) { Console.WriteLine($"Transaction: {(int)t.Attribute("id")} " + // transaction ID $"{{{(string)t.Attribute("type")}}}, " + // transaction type, e.g. keep, move, promote, purge, etc. $"{t.acxTime("time")}"); // convert Epoch "time" attribute to .NET DateTime object string tcomment = t.acxComment(); Console.WriteLine($"User: {(string)t.Attribute("user")}{(String.IsNullOrEmpty(tcomment) ? String.Empty : ", " + tcomment)}"); string fromStream = t.acxFromStream(); if (!String.IsNullOrEmpty(fromStream)) { Console.WriteLine($"From {fromStream} to {t.acxToStream()}"); // attributes that exist for promote transactions only } string virtualNamed = t.acxVirtualNamed(); if (!String.IsNullOrEmpty(virtualNamed)) { Console.WriteLine($"Virtual: {virtualNamed}"); // a promote or co operation } Console.WriteLine(); foreach (XElement v in t.Elements("version")) { string realNamed = v.acxRealNamed(); if (String.IsNullOrEmpty(realNamed)) { continue; // null in first (redundant) version element in promote transactions } string vcomment = v.acxComment(); if (!String.IsNullOrEmpty(vcomment)) { Console.WriteLine("\t" + vcomment); } string path = (string)v.Attribute("path"); if (!String.IsNullOrEmpty(path)) { Console.WriteLine($"\tEID: {eid} {path}"); } DateTime?mtime = v.acxTime("mtime"); // convert Epoch "mtime" attribute Console.WriteLine($"\tReal: {realNamed} {((mtime == null) ? String.Empty : "Modified: " + mtime)}"); string ancestorNamed = v.acxAncestorNamed(); if (!String.IsNullOrEmpty(ancestorNamed)) { Console.WriteLine($"\tAncestor: {ancestorNamed}"); } string mergedAgainstNamed = v.acxMergedAgainstNamed(); if (!String.IsNullOrEmpty(mergedAgainstNamed)) { Console.WriteLine($"\tMerged against: {mergedAgainstNamed}"); } Console.WriteLine(); } Console.WriteLine("--------------------------------------------------------"); } return(true); }
public static async Task <bool> userChangesAsync(string user, string startTime, string endTime) { Console.WriteLine($@"User: {user}, ""{startTime} - {endTime}""{Environment.NewLine}"); List <string> depots = await AcQuery.getDepotNameListAsync(); if (depots == null) { return(false); // operation failed, check log file } foreach (string depot in depots) { // start-end times reversed as workaround for AccuRev issue 15780 string time = $"{endTime} - {startTime}"; AcResult r1 = await AcCommand.runAsync($@"hist -p ""{depot}"" -t ""{time}"" -u ""{user}"" -k keep -fx"); if (r1 == null || r1.RetVal != 0) { return(false); // operation failed } XElement x1 = XElement.Parse(r1.CmdResult); foreach (XElement t in x1.Elements("transaction")) { int transID = (int)t.Attribute("id"); string tcomment = t.acxComment(); Console.WriteLine($"Depot: {depot}, {{{transID}}} {(DateTime)t.acxTime("time")}" + $"{(String.IsNullOrEmpty(tcomment) ? String.Empty : ", " + tcomment)}"); foreach (XElement v in t.Elements("version")) { string path = (string)v.Attribute("path"); Console.WriteLine($"\tEID: {(int)v.Attribute("eid")} {path} ({(string)v.Attribute("real")})"); string mergedAgainstNamed = v.acxMergedAgainstNamed(); Console.WriteLine($"\tReal: {v.acxRealNamed()}, Ancestor: {v.acxAncestorNamed()}" + $"{(String.IsNullOrEmpty(mergedAgainstNamed) ? String.Empty : ", Merged against: " + mergedAgainstNamed)}"); string realNamed = (string)v.Attribute("realNamedVersion"); AcResult r2 = await AcCommand.runAsync($@"annotate -v ""{realNamed}"" -fxtu ""{path}"""); if (r2 == null || r2.RetVal != 0) { return(false); // operation failed } // get this transaction from the annotate results XElement x2 = XElement.Parse(r2.CmdResult); XElement trans = (from a in x2.Descendants("trans") where (int)a.Attribute("number") == transID && // comparing transaction ID's (string)a.Attribute("principal_name") == user && (string)a.Attribute("version_name") == realNamed select a).SingleOrDefault(); if (trans != null) { XElement diff = trans.Parent; // get diff element for this transaction from annotate results foreach (XElement ln in diff.Elements("line")) // line elements are transaction element siblings { Console.WriteLine($"\tLine number: {(int)ln.Attribute("number")} \"{(string)ln.Attribute("type")}\" {{{(int)ln.Attribute("trans")}}}, {(string)ln}"); } } Console.WriteLine(); } } } return(true); }
// Run the AccuRev hist command for all streams in PromoCount.exe.config, generate the results and send it // to the daily log file PromoCountResults-YYYY-MM-DD.log created (or updated) in the same folder where // PromoCount.exe resides. Returns true if the operation succeeded, false otherwise. AcUtilsException // caught and logged in %LOCALAPPDATA%\AcTools\Logs\PromoCount-YYYY-MM-DD.log on hist command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <bool> promoCountAsync() { bool ret = false; // assume failure try { Dictionary <AcStream, Task <AcResult> > map = new Dictionary <AcStream, Task <AcResult> >(_selStreams.Count); Func <AcStream, Task <AcResult> > run = (stream) => { // start-end times reversed as workaround for AccuRev issue 15780 Task <AcResult> result = AcCommand.runAsync( $@"hist -fx -k promote -s ""{stream}"" -t ""{_endTime} - {_startTime}"""); lock (_locker) { map.Add(stream, result); } return(result); }; var tasks = from s in _depots.SelectMany(d => d.Streams) where _selStreams.OfType <StreamElement>().Any(se => se.Stream == s.Name) select run(s); AcResult[] arr = await Task.WhenAll(tasks); // finish running hist commands in parallel if (arr == null || arr.Any(r => r.RetVal != 0)) { return(false); } log($"Promotions to select streams from {_startTime} to {_endTime}.{Environment.NewLine}"); int tgrandtot = 0; int vgrandtot = 0; foreach (var ii in map.OrderBy(n => n.Key)) { log($"{ii.Key} {{{$"promotions\\versions"}}}:"); // key is stream AcResult r = ii.Value.Result; XElement xml = XElement.Parse(r.CmdResult); ILookup <string, XElement> look = xml.Elements("transaction") .ToLookup(n => (string)n.Attribute("user"), n => n); int tsubtot = 0; int vsubtot = 0; foreach (var jj in look.OrderBy(n => _users.getUser(n.Key))) { AcUser user = _users.getUser(jj.Key); int tnum = jj.Count(); int vnum = jj.Elements("version").Count(); string val = $"{{{tnum}\\{vnum}}}"; log($"\t{user.ToString().PadRight(40, '.')}{val.PadLeft(13, '.')}"); tsubtot += tnum; tgrandtot += tnum; vsubtot += vnum; vgrandtot += vnum; } log($"\tTotal {tsubtot} promotions and {vsubtot} versions.{Environment.NewLine}"); } log($"Grand total of {tgrandtot} promotions and {vgrandtot} versions."); ret = true; } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
private string SerializeCommand(AcCommand command) { return(command.ToString()); }
public void Execute(AcCommand command) { var sCommand = SerializeCommand(command); _driver.Send(sCommand); }