// 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); }
// Returns the content for our HTML file. private static XDocument buildReport(DateTime past) { XDocument doc = new XDocument( new XDocumentType("HTML", null, null, null), new XElement("html", new XAttribute("lang", "en"), new XElement("head", new XElement("meta", new XAttribute("charset", "utf-8")), new XElement("meta", new XAttribute("name", "description"), new XAttribute("content", "Promotions to select streams during the past specified number of hours.")), new XElement("title", "Promotions since " + past.ToString("f")), new XElement("style", $@"body {{ background-color: Gainsboro; color: #0000ff; font-family: Arial, sans-serif; font-size: 13px; margin: 10px; }} table {{ background-color: #F1F1F1; color: #000000; font-size: 12px; border: 2px solid black; padding: 10px; }}" ) ), new XElement("body", new XElement("p", "Promotions since " + past.ToString("f") + " to streams:"), new XElement("ul", from s in _selStreams.OfType <StreamElement>() orderby s.Stream select new XElement("li", s.Stream)), new XElement("table", new XElement("thead", new XElement("tr", new XElement("td", "TransID"), new XElement("td", "TransTime"), new XElement("td", "Promoter"), new XElement("td", "Elements") ) ), new XElement("tbody", from t in _hist.Elements("transaction") orderby _users.getUser((string)t.Attribute("user")), t.acxTime("time") descending // by user with their latest transactions on top select new XElement("tr", new XElement("td", (int)t.Attribute("id")), new XElement("td", ((DateTime)t.acxTime("time")).ToString("g")), new XElement("td", _users.getUser((string)t.Attribute("user")) + " (" + (string)t.Attribute("user") + ")", new XElement("br"), business((string)t.Attribute("user")), new XElement("br"), mobile((string)t.Attribute("user"))), new XElement("td", new XElement("table", new XElement("caption", t.acxComment()), new XElement("thead", new XElement("tr", new XElement("td", "EID"), new XElement("td", "Element"), new XElement("td", "Location"), new XElement("td", "Real"), new XElement("td", "Virtual"), new XElement("td", "Status") ) ), new XElement("tbody", from v in t.Elements("version") orderby Path.GetFileName((string)v.Attribute("path")) select new XElement("tr", new XElement("td", (int)v.Attribute("eid")), new XElement("td", Path.GetFileName((string)v.Attribute("path"))), new XElement("td", Path.GetDirectoryName((string)v.Attribute("path"))), new XElement("td", $"{(string)v.Attribute("realNamedVersion")} ({(string)v.Attribute("real")})"), new XElement("td", $"{(string)v.Attribute("virtualNamedVersion")} ({(string)v.Attribute("virtual")})"), new XElement("td", (Stat.getElement(v) != null ? Stat.getElement(v).Status : "(earlier)")) ) ) ) ) ) ) ) ) )); return(doc); }
// Returns the content for our HTML file. private static XDocument buildReport(DateTime past) { // transactions where one or more versions have overlap status IEnumerable <XElement> trans = from t in _hist.Elements("transaction") where Stat.getElement(t.Element("version")) != null select t; ILookup <string, XElement> map = trans.ToLookup(n => (string)n.Attribute("streamName"), n => n); XDocument doc = new XDocument( new XDocumentType("HTML", null, null, null), new XElement("html", new XAttribute("lang", "en"), new XElement("head", new XElement("meta", new XAttribute("charset", "utf-8")), new XElement("meta", new XAttribute("name", "description"), new XAttribute("content", "Promotions to select depots within the past specified number of hours that have versions with overlap status.")), new XElement("title", "Promotions with overlaps since " + past.ToString("f")), new XElement("style", $@"body {{ background-color: Gainsboro; color: #0000ff; font-family: Arial, sans-serif; font-size: 13px; margin: 10px; }} table {{ background-color: #F1F1F1; color: #000000; font-size: 12px; border: 2px solid black; padding: 10px; }}" ) ), new XElement("body", new XElement("p", "Promotions with overlaps since " + past.ToString("f") + " exist in:"), new XElement("ul", from s in map orderby s.Key // stream name select new XElement("li", s.Key)), new XElement("table", new XElement("thead", new XElement("tr", new XElement("td", "TransID"), new XElement("td", "TransTime"), new XElement("td", "Promoter"), new XElement("td", "Elements") ) ), new XElement("tbody", from t in trans orderby _users.getUser((string)t.Attribute("user")), t.acxTime("time") descending // by user with their latest transactions on top select new XElement("tr", new XElement("td", (int)t.Attribute("id")), new XElement("td", ((DateTime)t.acxTime("time")).ToString("g")), new XElement("td", _users.getUser((string)t.Attribute("user")) + " (" + (string)t.Attribute("user") + ")", new XElement("br"), business((string)t.Attribute("user")), new XElement("br"), mobile((string)t.Attribute("user"))), new XElement("td", new XElement("table", new XElement("caption", t.acxComment()), new XElement("thead", new XElement("tr", new XElement("td", "EID"), new XElement("td", "Element"), new XElement("td", "Location"), new XElement("td", "Real"), new XElement("td", "Virtual"), new XElement("td", "Status") ) ), new XElement("tbody", from v in t.Elements("version") where (int?)v.Attribute("eid") != null orderby Path.GetFileName((string)v.Attribute("path")) select new XElement("tr", new XElement("td", (int)v.Attribute("eid")), new XElement("td", Path.GetFileName((string)v.Attribute("path"))), new XElement("td", Path.GetDirectoryName((string)v.Attribute("path"))), new XElement("td", $"{(string)v.Attribute("realNamedVersion")} ({(string)v.Attribute("real")})"), new XElement("td", $"{(string)v.Attribute("virtualNamedVersion")} ({(string)v.Attribute("virtual")})"), new XElement("td", (Stat.getElement(v) != null ? Stat.getElement(v).Status : "(earlier)")) ) ) ) ) ) ) ) ) ) ); return(doc); }