public void RemoveCachedErrors()
		{
			using (_cache = new VssFileCache(_options.CacheDir, _options.SourceSafeIni))
			{
				_cache.DropAllErrors();
			}
		}
Example #2
0
		public void Import(Options opts, List<Commit> commits, bool startNewSession, Action<float> progress = null)
		{
			StopImport = false;
			DogWatch = DateTimeOffset.Now;

			if(startNewSession && File.Exists(DataFileName))
				File.Delete(DataFileName);

			_opts = opts;

			_unimportants = opts
				.Config["unimportant-diff"]
				.Select(v => {
					var sep = v.IndexOf('?');
					if (sep == -1)
						throw new ApplicationException("Incorrect unimportant-diff: " + v + "\nAbsent separator '?' between filename and unimportant regex");

					var fileNameRx = new Regex(v.Substring(0, sep), RegexOptions.IgnoreCase);
					var regex = new Regex(v.Substring(sep + 1), RegexOptions.IgnoreCase);

					return Tuple.Create(fileNameRx, regex);
				})
				.ToList()
			;

			// load censores
			_censors = LoadCensors(opts);

			var fromCommit = 0;

			if (!startNewSession)
			{
				if (File.Exists(DataFileName))
				{
					fromCommit = File.ReadAllLines(DataFileName)
						.Select(x => Int32.Parse(x) + 1)
						.DefaultIfEmpty(0)
						.Last()
					;
				}

				if (MessageBox.Show(string.Format("Cleanu work tree and start import from commit #{0} by {1}", fromCommit, commits[fromCommit].User), "Confirmation", MessageBoxButtons.OKCancel) != DialogResult.OK)
					return;

				if (opts.ImportDriver == "tfs")
				{
					new TfsDriver(opts, Console.Out, false).CleanupWorkingTree();
				}
			}

			using (_cache = new VssFileCache(opts.CacheDir, _opts.SourceSafeIni))
			using(var log = File.CreateText(LogFileName))
			{
				log.AutoFlush = true;

				try
				{
					IDestinationDriver driver;
					if (opts.ImportDriver == "git")
					{
						driver = new GitDriver(opts.GitExe, opts.GitRepoDir, opts.GitDefaultAuthorDomain, log);
					}
					else if (opts.ImportDriver == "tfs")
					{
						driver = new TfsDriver(opts, log, true);
					}
					else
					{
						driver = new SvnDriver(opts.SvnWorkTreeDir, log);
					}

					for (var i = fromCommit; i < commits.Count; i++)
					{
						var c = commits[i];

						Console.WriteLine("[{2,6}/{3}] Import: {0:yyyy-MMM-dd HH:ss:mm}, by {1}", c.At, c.User, i, commits.Count);
						if (progress != null)
							progress((float)i / commits.Count);

						DogWatch = DateTimeOffset.Now;

						driver.StartRevision();

						DogWatch = DateTimeOffset.Now;

						LoadRevision(driver, c, log);

						DogWatch = DateTimeOffset.Now;

						driver.CommitRevision(commits[i].User, c.Comment, commits[i].At);

						DogWatch = DateTimeOffset.Now;

						// OK
						File.AppendAllText(DataFileName, i + "\n");

						if (StopImport)
							break;
					}
				}
				catch (Exception ex)
				{
					log.WriteLine(ex.ToString());
					throw;
				}
			}

			DogWatch = null;

			if (StopImport)
			{
				Console.WriteLine("Import interrupted.");
			}
			else
			{
				Console.WriteLine("Import complete.");

				if (opts.ImportDriver == "git" && !string.IsNullOrWhiteSpace(opts.GitStartAfterImport))
				{
					Process.Start(opts.GitStartAfterImport, opts.GitStartAfterImportArgs.Replace("%REPODIR%", opts.GitRepoDir));
				}
			}
		}
		public void BuildStats(List<FileRevision> list)
		{
			// dump info about versions count per file
			using (var versionsCountLog = File.CreateText(VersionsCountFileName))
			{
				var listG = list
					.GroupBy(f => f.FileSpec)
					.Select(g => new { Count = g.Count(), Spec = g.Key })
					.OrderByDescending(x => x.Count)
					.ToList()
				;

				listG.ForEach(g => versionsCountLog.WriteLine("{0,6} {1}", g.Count, g.Spec));
			}

			// reduce pinned files to single revision
			list = list
				.GroupBy(f => f.FileSpec)
				.Select(g => {
					if (IsShouldBePinned(g.Key))
						return g.Take(1).ToArray();
					return g.ToArray();
				})
				.SelectMany(x => x)
				.ToList()
			;

			using (var cache = new VssFileCache(_options.CacheDir, _options.SourceSafeIni))
			using (var errLog = File.CreateText(ErrorsFileName))
			using (var onlyLastVersionsLog = File.CreateText(OnlyLastVersionFileName))
			{
				errLog.AutoFlush = true;
				onlyLastVersionsLog.AutoFlush = true;

				// undone list
				using (var log = File.CreateText(UndoneVersionsCountFileName))
				{
					var listG = list
						.Where(v => cache.GetFileInfo(v.FileSpec, v.VssVersion) == null)
						.GroupBy(f => f.FileSpec)
						.Select(g => new { Count = g.Count(), Spec = g.Key })
						.OrderByDescending(x => x.Count)
						.ToList()
					;

					listG.ForEach(g => log.WriteLine("{0,6} {1}", g.Count, g.Spec));
				}

				var cached = 0;
				var errors = 0;
				var onlyLastVersions = 0;
				var notCached = 0;

				var onlyLastVersionSpecs = new HashSet<string>();

				foreach (var file in list)
				{
					if (cache.GetFilePath(file.FileSpec, file.VssVersion) != null)
					{
						cached++;
					}
					else
					{
						var err = cache.GetFileError(file.FileSpec, file.VssVersion);
						if (!string.IsNullOrWhiteSpace(err))
						{
							if (err == "not-retained")
							{
								if (!onlyLastVersionSpecs.Contains(file.FileSpec))
								{
									onlyLastVersions++;
									onlyLastVersionsLog.WriteLine("{0}", file.FileSpec);
									onlyLastVersionSpecs.Add(file.FileSpec);
								}
							}
							else
							{
								errors++;
								errLog.WriteLine("{0}@{1}\n\t{2}", file.FileSpec, file.VssVersion, err);
							}
							cached++;
						}
						else
						{
							notCached++;
						}
					}
				}

				Console.WriteLine("Cached: {0} (Errors: {1})  Not Cached: {2}", cached, errors, notCached);
				Console.WriteLine("Only Last Version: {0}", onlyLastVersions);
				Console.WriteLine("Not Cached: {0:0.00}%", 100.0 * notCached / list.Count);
				Console.WriteLine();
			}
		}
		public void Build(List<FileRevision> versions, Action<float> progress = null)
		{
			var sw = Stopwatch.StartNew();

			_tempDir = Path.Combine(Environment.CurrentDirectory, "vss-temp");
			Directory.CreateDirectory(_tempDir);

			_db = _options.DB.Value;
			var originalVersions = versions.ToList();

			using(_cache = new VssFileCache(_options.CacheDir, _db.SrcSafeIni))
			{
				// filterout cached versions
				if (!_options.Force)
				{
					Console.WriteLine("Skip already cached versions...");

					var cached = 0;
					var notRetained = 0;
					var errors = 0;

					versions.Clear();
					foreach (var file in originalVersions)
					{
						if (_cache.GetFilePath(file.FileSpec, file.VssVersion) != null)
						{
							cached++;
							continue;
						}

						if (!string.IsNullOrWhiteSpace(_cache.GetFileError(file.FileSpec, file.VssVersion)))
						{
							var err = _cache.GetFileError(file.FileSpec, file.VssVersion);

							if (err == "not-retained")
								notRetained++;
							else
								errors++;

							continue;
						}

						versions.Add(file);
					}

					Console.WriteLine("Cached(good): {0}", cached);
					Console.WriteLine("Cached(errors): {0}", errors);
					Console.WriteLine("Cached(not retained version): {0}", notRetained);
					Console.WriteLine("Not Cached: {0}", versions.Count);
				}
				Console.WriteLine();

				// sort versions
				versions = versions
					.GroupBy(f => f.FileSpec)
					// order by versions count. posible you do not want to convert all versions for some autogenerated files
					.OrderBy(g => g.Count())
					// start retrieveing from recent (high versions) to ancient (version 1)
					.SelectMany(g => g.OrderByDescending(v => v.VssVersion))
					.ToList()
				;

				using(_log = File.CreateText(LogFileName))
				{
					_log.AutoFlush = true;

					// cache
					var fileGroups = versions.GroupBy(v => v.FileSpec).ToList();

					for (var j = 0; j < fileGroups.Count; j++)
					{
						var fileGroup = fileGroups[j];

						Console.Write("[{0}/{1}] Get: {3,5} x {2}", j, fileGroups.Count, fileGroup.Key, fileGroup.Count());
						if (progress != null)
							progress((float)j / fileGroups.Count);

						foreach (var fg in fileGroup)
						{
							Process(fg);
						}

						Console.WriteLine();
					}
				}

				// build cached versions list
				BuildCachedVersionsList(originalVersions);
			}

			sw.Stop();

			Console.WriteLine();
			Console.WriteLine("Building cache complete. Take {0}", sw.Elapsed);
		}
		public void Build(Options opts, IList<Tuple<string, int>> files, Action<float> progress = null)
		{
			var stopWatch = new Stopwatch();
			stopWatch.Start();

			using (var cache = new VssFileCache(opts.CacheDir + "-revs", opts.SourceSafeIni))
			using(var wr = File.CreateText(DataFileName))
			using(var log = File.CreateText(LogFileName))
			{
				wr.AutoFlush = log.AutoFlush = true;

				var db = opts.DB.Value;

				var findex = 0;
				foreach (var spec in files.Select(t => t.Item1))
				{
					findex++;

					try{
						IVSSItem item = db.VSSItem[spec];
						var head = item.VersionNumber;

						var timestamp = item.VSSVersion.Date.Ticks;

						var cachedData = cache.GetFilePath(spec, head, timestamp);
						if (cachedData != null)
						{
							Console.Write("c");
							Save(wr, Load(cachedData));
							// next file
							continue;
						}

						Console.Write("[{0,5}/{1,5}] {2} ", findex, files.Count, item.Spec);
						if (progress != null)
							progress((float)findex / files.Count);

						var rotationIndex = 0;
						var rotationArray = @"|/-\|/-\".ToCharArray();

						var latestOnly = IsLatestOnly(opts, spec);

						var itemRevisions = new List<FileRevision>();
						foreach (IVSSVersion ver in item.Versions)
						{
							Console.Write("{0}\b", rotationArray[rotationIndex++ % rotationArray.Length]);

							if (ver.Action.StartsWith("Labeled ") || ver.Action.StartsWith("Branched "))
								continue;

							if (!ver.Action.StartsWith("Checked in ") && !ver.Action.StartsWith("Created ") && !ver.Action.StartsWith("Archived ") && !ver.Action.StartsWith("Rollback to"))
							{
								log.WriteLine("Unknown action: " + ver.Action);
							}

							var user = ver.Username.ToLowerInvariant();

							var fileVersionInfo = new FileRevision {
								FileSpec = item.Spec,
								At = ver.Date.ToUniversalTime(),
								Comment = ver.Comment,
								VssVersion = ver.VersionNumber,
								User = user
							};
							try
							{
								// can throw exception, but it is not critical
								fileVersionInfo.Physical = ver.VSSItem.Physical;
							}
							catch (Exception ex)
							{
								Console.WriteLine("ERROR: Get Physical: " + ex.Message);
								log.WriteLine("ERROR: Get Physical: {0}", spec);
								log.WriteLine(ex.ToString());
								fileVersionInfo.Physical = "_UNKNOWN_";
							}
							itemRevisions.Add(fileVersionInfo);

							if (latestOnly)
								break;

							Console.Write('.');
						}

						Console.WriteLine(" ");

						if (itemRevisions.Count > 0)
						{
							// some time date of items wrong, but versions - correct.
							// sort items in correct order and fix dates
							itemRevisions = itemRevisions.OrderBy(i => i.VssVersion).ToList();

							// fix time. make time of each next item greater than all previous
							var notEarlierThan = itemRevisions[0].At;
							for (int i = 1; i < itemRevisions.Count; i++)
							{
								if (itemRevisions[i].At < notEarlierThan)
								{
									itemRevisions[i].At = notEarlierThan + TimeSpan.FromMilliseconds(1);
									itemRevisions[i].Comment += "\n! Time was fixed during VSS -> SVN conversion. Time can be incorrect !\n";
									itemRevisions[i].Comment = itemRevisions[i].Comment.Trim();
								}

								notEarlierThan = itemRevisions[i].At;
							}
						}

						Save(wr, itemRevisions);

						var tempFile = Path.GetTempFileName();
						try
						{
							using (var sw = new StreamWriter(tempFile, false, Encoding.UTF8))
								Save(sw, itemRevisions);

							cache.AddFile(spec, head, timestamp, tempFile, false);
						}
						finally
						{
							if (File.Exists(tempFile))
								File.Delete(tempFile);
						}
					}
					catch(Exception ex)
					{
						Console.WriteLine("ERROR: {0}", spec);
						log.WriteLine("ERROR: {0}", spec);
						log.WriteLine(ex.ToString());
					}
				}
			}

			stopWatch.Stop();
			Console.WriteLine("Build files versions list complete. Take: {0}", stopWatch.Elapsed);
		}