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);
		}
Beispiel #2
0
		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");
				}
			}
		}