public void Build(Options opts, IList<Tuple<string, int>> files) { var coDict = new Dictionary<DateTime, List<Tuple<string, string>>>(); var xrefsCo = new XRefMap(); var xrefs = new XRefMap(); foreach (var file in files.Select(t => t.Item1)) { Console.WriteLine(file); var item = opts.DB.Value.VSSItem[file]; foreach (IVSSItem vssLink in item.Links) { if (!String.Equals(item.Spec, vssLink.Spec, StringComparison.OrdinalIgnoreCase) && !vssLink.Deleted) xrefs.AddRef(item.Spec, vssLink.Spec); foreach (IVSSCheckout vssCheckout in vssLink.Checkouts) { xrefsCo.AddRef(item.Spec, vssCheckout.Username + " at " + vssCheckout.Date); var coDate = vssCheckout.Date.Date; List<Tuple<string, string>> list; if(!coDict.TryGetValue(coDate, out list)) { list = new List<Tuple<string, string>>(); coDict[coDate] = list; } list.Add(Tuple.Create(vssCheckout.Username, item.Spec)); } } } xrefs.Save(DataFileName); xrefs.Save(DataFileUiName, true); xrefsCo.Save(DataFileCoName, true); // save co dict by dates using (var tw = File.CreateText(DataFileCoByDateName)) { foreach (var kvp in coDict.OrderByDescending(kvp => kvp.Key)) { tw.WriteLine("{0:yyyy-MM-dd} ({1} days ago)", kvp.Key, (int)(DateTime.Now - kvp.Key).TotalDays); foreach (var tuple in kvp.Value) { tw.WriteLine("\t{0} at {1}", tuple.Item1, tuple.Item2); } tw.WriteLine(); } } Console.WriteLine("VSS links: {0} pcs", xrefs.Map.Count); Console.WriteLine("Checkouts: {0} pcs", xrefsCo.Map.Count); }
public XRefMap Inverse() { var inversed = new XRefMap(); foreach (var kvp in Map) { foreach (var xref in kvp.Value) { inversed.AddRef(xref, kvp.Key); } } return inversed; }
public void Build(Options opts, IList<Tuple<string, int>> importSpecs, Dictionary<string, bool> roots) { if(!Directory.Exists("scripts")) Directory.CreateDirectory("scripts"); using(var swRmLocal = File.CreateText("scripts\\remove-local.bat")) using(var swRmVss = File.CreateText("scripts\\remove-vss.bat")) { swRmVss.WriteLine("set PATH=%PATH%;C:\\Program Files (x86)\\Microsoft Visual SourceSafe"); swRmVss.WriteLine("set SSDIR={0}", Path.GetDirectoryName(opts.SourceSafeIni)); swRmVss.WriteLine("set SSUSER={0}", opts.Config["source-safe-user"].LastOrDefault() ?? "<TODO>"); swRmVss.WriteLine("set SSPWD={0}", opts.Config["source-safe-password"].LastOrDefault() ?? "<TODO>"); swRmVss.WriteLine(); // remove vss projects, local files foreach (var kvp in roots) { swRmVss.WriteLine("ss.exe DELETE \"{0}\"", kvp.Key); if(kvp.Value) swRmLocal.WriteLine("rd /S /Q \"{0}\"", kvp.Key.TrimStart("$/\\".ToCharArray()).Replace('/', '\\').TrimEnd('\\')); else swRmLocal.WriteLine("del /F \"{0}\"", kvp.Key.TrimStart("$/\\".ToCharArray()).Replace('/', '\\')); } } // generate script for update links information + new links.db file using(var sw = File.CreateText("scripts\\apply-link-tokens.bat")) { var file2Token = new XRefMap(); var linksDb = opts.Config["links-db-latest"].FirstOrDefault(); if (linksDb != null) { IDisposable disp = null; try { var user = opts.Config["links-db-user"].FirstOrDefault(); var password = opts.Config["links-db-password"].FirstOrDefault(); if (user != null && password != null) { disp = WindowsImpersonation.Impersonate(new NetworkCredential(user, password)); } // get max file if (Directory.Exists(linksDb)) { linksDb = Directory .GetFiles(linksDb, "*.gz", SearchOption.AllDirectories) .Select(f => new { Ind = Int32.Parse(Path.GetFileNameWithoutExtension(f)), Path = f }) .OrderByDescending(f => f.Ind) .First() .Path ; } using (var src = new GZipStream(File.OpenRead(linksDb), CompressionMode.Decompress)) using (var dst = File.Create(string.Format("_links_db_token_file.{0}.original.txt", Path.GetFileNameWithoutExtension(linksDb)))) src.CopyTo(dst); using (var sr = new StreamReader(new GZipStream(File.OpenRead(linksDb), CompressionMode.Decompress))) file2Token.LoadTokenFile(sr); } finally { if(disp != null) disp.Dispose(); } } var token2Files = file2Token.Inverse(); var importedLinks = new XRefMap(); importedLinks.Load(LinksBuilder.DataFileUiName); // 1. Build set with imported files var importedSet = new HashSet<string>(); foreach (var importedLink in importedLinks.Map.Keys) { importedSet.Add(importedLink); } // files which added to link DB. var add2DbSet = new HashSet<string>(); foreach (var importedLink in importedLinks.Map.Keys) { var otherLinks = importedLinks.Map[importedLink].ToList(); var links = otherLinks.ToList(); links.Insert(0, importedLink); // find or construct token for this bunch of files string token = null; foreach (var link in links) { if(file2Token.Map.ContainsKey(link)) { token = file2Token.Map[link][0]; break; } } // Build new token if(token == null) { token = Path.GetFileName(importedLink).ToLowerInvariant(); if(token2Files.Map.ContainsKey(token)) token = token + "!" + DateTimeOffset.UtcNow.Ticks; Debug.Assert(token2Files.Map.ContainsKey(token) == false); } // buld list which should be added to db var forAdd2Db = otherLinks.Where(l => !importedSet.Contains(l) && !add2DbSet.Contains(l) && !file2Token.Map.ContainsKey(l)).ToList(); // mark imported file with token var file = importedLink.Trim("$/\\".ToCharArray()); Console.WriteLine("ihs:link-token: {0}", file); sw.WriteLine("svn ps ihs:link-token \"{0}\" \"{1}\"", token, file); // add other links into DB forAdd2Db.ForEach(l => { Console.WriteLine("Add 2 DB: {0}", l); file2Token.AddRef(l, token); token2Files.AddRef(token, l); add2DbSet.Add(l); }); Console.WriteLine(); } // check all imported specs (except already handled) if they has token in db foreach (var imported in importSpecs.Select(t => t.Item1).Where(i => !importedSet.Contains(i))) { List<string> files; if(!file2Token.Map.TryGetValue(imported, out files)) continue; var token = files[0]; // mark imported file with token var file = imported.Trim("$/\\".ToCharArray()); Console.WriteLine("Mark with ihs:link-token: {0}", file); sw.WriteLine("svn ps ihs:link-token \"{0}\" \"{1}\"", token, file); } if (linksDb != null) { var updated = string.Format("_links_db_token_file.{0}.updated.txt", Path.GetFileNameWithoutExtension(linksDb)); file2Token.SaveTokenFile(updated); File.AppendAllText(updated, "# hash: skip"); } } }