// 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); }
// 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 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); }
// 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; }
// 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); }
// 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); }
// 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)); }
// 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; }
// 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; }
// 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 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 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); }