예제 #1
0
		public void SingleBranch_PlaysInSequence()
		{
			var now = DateTime.Now;
			var file1 = new FileInfo("file1");
			var file2 = new FileInfo("file2").WithBranch("branch", "1.1.0.2");

			var commit0 = new Commit("id0") { Index = 1 }
					.WithRevision(file1, "1.1", time: now)
					.WithRevision(file2, "1.1", time: now);

			var commit1 = new Commit("id1") { Index = 2 }
					.WithRevision(file1, "1.2", time: now + TimeSpan.FromMinutes(2))
					.WithRevision(file2, "1.2", time: now + TimeSpan.FromMinutes(2), mergepoint: "1.1.2.1");

			var commit2 = new Commit("branch0") { Index = 3 }
					.WithRevision(file2, "1.1.2.1", time: now + TimeSpan.FromMinutes(1));

			var commits = new[] { commit0, commit1, commit2 };
			var branchpoints = new Dictionary<string, Commit>()
			{
				{ "branch", commit0 }
			};
			var branches = new BranchStreamCollection(commits, branchpoints);
			commit1.MergeFrom = commit2;

			var player = new CommitPlayer(MockRepository.GenerateStub<ILogger>(), branches);
			var result = player.Play().Select(c => c.CommitId).ToList();

			Assert.IsTrue(result.SequenceEqual("id0", "branch0", "id1"));
		}
예제 #2
0
        /// <summary>
        /// Create extra commits for files that have been marked as "head-only".
        /// </summary>
        public void CreateHeadOnlyCommits(IEnumerable <string> headOnlyBranches, BranchStreamCollection streams,
                                          FileCollection allFiles)
        {
            var branches     = SortBranches(headOnlyBranches, streams);
            var branchMerges = new Dictionary <string, string>();

            if (branches.Any())
            {
                m_log.DoubleRuleOff();
                m_log.WriteLine("Creating head-only commits");
            }

            using (m_log.Indent())
            {
                foreach (var branch in branches)
                {
                    // record where this branch will be merged to
                    if (streams[branch].Predecessor != null)
                    {
                        branchMerges[streams[branch].Predecessor.Branch] = branch;
                    }

                    string branchMergeFrom;
                    branchMerges.TryGetValue(branch, out branchMergeFrom);

                    CreateHeadOnlyCommit(branch, streams, allFiles, branchMergeFrom);
                }
            }
        }
		public void Roots()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsTrue(streams["MAIN"] == m_commits[0]);
			Assert.IsTrue(streams["branch"] == m_commits[1]);
		}
		public void Heads()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsTrue(streams.Head("MAIN") == m_commits[2]);
			Assert.IsTrue(streams.Head("branch") == m_commits[1]);
		}
예제 #5
0
		/// <summary>
		/// Create extra commits for files that have been marked as "head-only".
		/// </summary>
		public void CreateHeadOnlyCommits(IEnumerable<string> headOnlyBranches, BranchStreamCollection streams,
				FileCollection allFiles)
		{
			var branches = SortBranches(headOnlyBranches, streams);
			var branchMerges = new Dictionary<string, string>();

			if (branches.Any())
			{
				m_log.DoubleRuleOff();
				m_log.WriteLine("Creating head-only commits");
			}

			using (m_log.Indent())
			{
				foreach (var branch in branches)
				{
					// record where this branch will be merged to
					if (streams[branch].Predecessor != null)
						branchMerges[streams[branch].Predecessor.Branch] = branch;

					string branchMergeFrom;
					branchMerges.TryGetValue(branch, out branchMergeFrom);

					CreateHeadOnlyCommit(branch, streams, allFiles, branchMergeFrom);
				}
			}
		}
		public void Construct()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsTrue(streams["MAIN"].ToList().Select(c => c.CommitId).SequenceEqual("1", "3"));
			Assert.IsTrue(streams["branch"].ToList().Single().CommitId == "2");
			Assert.IsTrue(streams.Verify());
		}
		public void Construct_IgnoredBranch()
		{
			// remove 'branch' from the list of branchpoints, simulating an ignored branch
			m_branchpoints.Remove("branch");
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsFalse(streams["branch"].ToList().Any());
		}
예제 #8
0
 public Importer(ILogger log, IConfig config, UserMap userMap, BranchStreamCollection branches,
                 IDictionary <string, Commit> tags, Cvs cvs)
 {
     m_log      = log;
     m_config   = config;
     m_userMap  = userMap;
     m_branches = branches;
     m_tags     = tags;
     m_cvs      = cvs;
     m_player   = new CommitPlayer(log, branches);
 }
예제 #9
0
		public Importer(ILogger log, IConfig config, UserMap userMap, BranchStreamCollection branches,
				IDictionary<string, Commit> tags, Cvs cvs)
		{
			m_log = log;
			m_config = config;
			m_userMap = userMap;
			m_branches = branches;
			m_tags = tags;
			m_cvs = cvs;
			m_player = new CommitPlayer(log, branches);
		}
예제 #10
0
        private void CreateHeadOnlyCommit(string branch, BranchStreamCollection streams, FileCollection allFiles, string branchMergeFrom)
        {
            var headOnlyState = m_headOnlyState[branch];
            var commitId      = String.Format("headonly-{0}", branch);
            var commit        = new Commit(commitId);

            var message = String.Format("Adding head-only files to {0}", m_branchRenamer.Process(branch));

            foreach (var file in headOnlyState.LiveFiles.OrderBy(i => i, StringComparer.OrdinalIgnoreCase))
            {
                var fileRevision = new FileRevision(allFiles[file], headOnlyState[file],
                                                    mergepoint: Revision.Empty, time: DateTime.Now, author: "", commitId: commitId);
                fileRevision.AddMessage(message);
                commit.Add(fileRevision);
            }

            // check for a merge
            if (branchMergeFrom != null)
            {
                Commit mergeSource = streams.Head(branchMergeFrom);
                if (mergeSource.CommitId.StartsWith("headonly-"))
                {
                    commit.MergeFrom = mergeSource;

                    // check for deleted files
                    var fileLookup = new HashSet <string>(commit.Select(r => r.File.Name));
                    foreach (var r in mergeSource)
                    {
                        if (!fileLookup.Contains(r.File.Name))
                        {
                            var fileRevision = new FileRevision(
                                file: r.File,
                                revision: Revision.Empty,                                           // a bit lazy, but I think we can get away with it
                                mergepoint: Revision.Empty,
                                time: DateTime.Now,
                                author: "",
                                commitId: commitId,
                                isDead: true);
                            fileRevision.AddMessage(message);
                            commit.Add(fileRevision);
                        }
                    }
                }
            }

            if (commit.Any())
            {
                m_log.WriteLine("Added commit {0}", commitId);
                streams.AppendCommit(commit);
            }
        }
예제 #11
0
        private static void Analyse()
        {
            var parser          = new CvsLogParser(m_config.Sandbox, m_config.CvsLogFileName, m_config.BranchMatcher);
            var builder         = new CommitBuilder(m_log, parser.Parse());
            var exclusionFilter = new ExclusionFilter(m_log, m_config);

            IEnumerable <Commit> commits = builder.GetCommits()
                                           .SplitMultiBranchCommits()
                                           .FilterCommitsOnExcludedBranches()
                                           .FilterExcludedFiles(exclusionFilter)
                                           .AddCommitsToFiles()
                                           .Verify(m_log)
                                           .ToListIfNeeded();

            // build lookup of all files
            var allFiles      = new FileCollection(parser.Files);
            var includedFiles = new FileCollection(parser.Files.Where(f => m_config.IncludeFile(f.Name)));

            WriteAllCommitsLog(commits);
            WriteExcludedFileLog(parser);

            var branchResolver = ResolveBranches(commits, includedFiles);

            commits = branchResolver.Commits;

            var tagResolver = ResolveTags(commits, includedFiles);

            commits = tagResolver.Commits;

            WriteTagLog("allbranches.log", branchResolver, parser.ExcludedBranches, m_config.BranchRename);
            WriteTagLog("alltags.log", tagResolver, parser.ExcludedTags, m_config.TagRename);
            WriteUserLog("allusers.log", commits);

            var streams = commits.SplitBranchStreams(branchResolver.ResolvedTags);

            // resolve merges
            var mergeResolver = new MergeResolver(m_log, streams);

            mergeResolver.Resolve();

            WriteBranchLogs(streams);

            // add any "head-only" files
            exclusionFilter.CreateHeadOnlyCommits(m_config.HeadOnlyBranches, streams, allFiles);

            // store data needed for import
            m_streams = streams;
        }
예제 #12
0
        private static void WriteBranchLogs(BranchStreamCollection streams)
        {
            foreach (var branch in streams.Branches)
            {
                var filename = String.Format("commits-{0}.log", branch);
                using (var writer = m_log.OpenDebugFile(filename))
                {
                    writer.WriteLine("Branch: {0}", branch);
                    writer.WriteLine();

                    for (var c = streams[branch]; c != null; c = c.Successor)
                    {
                        WriteCommitLog(writer, c);
                    }
                }
            }
        }
예제 #13
0
        private List <string> SortBranches(IEnumerable <string> headOnlyBranches, BranchStreamCollection streams)
        {
            // build a set of branches that we care about
            var branches = new HashSet <string> {
                "MAIN"
            };

            foreach (var branch in headOnlyBranches)
            {
                branches.Add(branch);
            }

            // get a list of all branches in order and filter it
            var list = streams.OrderedBranches.Where(b => branches.Contains(b)).ToList();

            list.Reverse();
            return(list);
        }
예제 #14
0
		public void NoBranches_PlaysInSequence()
		{
			var file1 = new FileInfo("file1");
			var file2 = new FileInfo("file2");

			var commit0 = new Commit("id0") { Index = 1 }
					.WithRevision(file1, "1.1")
					.WithRevision(file2, "1.1");

			var commit1 = new Commit("id1") { Index = 2 }
					.WithRevision(file1, "1.2");

			var commit2 = new Commit("id2") { Index = 3 }
					.WithRevision(file2, "1.2");

			var commits = new[] { commit0, commit1, commit2 };
			var branches = new BranchStreamCollection(commits, new Dictionary<string, Commit>());

			var player = new CommitPlayer(MockRepository.GenerateStub<ILogger>(), branches);
			var result = player.Play().ToList();

			Assert.IsTrue(result.SequenceEqual(commits));
		}
예제 #15
0
		public void CrossedMerge_LongerHistoryOnMergeDestination()
		{
			var commits = new List<Commit>()
			{
				new Commit("initial1").WithRevision(m_file, "1.1"),
				new Commit("initial2").WithRevision(m_file, "1.2"),
				new Commit("initial3").WithRevision(m_file, "1.3"),
				new Commit("branch1").WithRevision(m_file, "1.3.2.1"),
				new Commit("branch2").WithRevision(m_file, "1.3.2.2"),
				new Commit("merge1").WithRevision(m_file, "1.4", mergepoint: "1.3.2.2"),
				new Commit("merge2").WithRevision(m_file, "1.5", mergepoint: "1.3.2.1"),
			};
			m_file.WithBranch("branch", "1.3.0.2");

			var branchpoints = new Dictionary<string, Commit>()
			{
				{ "branch", commits[0] }
			};

			var streams = new BranchStreamCollection(commits, branchpoints);
			var resolver = new MergeResolver(m_logger, streams);
			resolver.Resolve();

			Assert.IsTrue(streams["MAIN"].ToList().Select(c => c.CommitId).SequenceEqual("initial1", "initial2", "initial3", "merge1", "merge2"));
			Assert.IsTrue(streams["branch"].ToList().Select(c => c.CommitId).SequenceEqual("branch2", "branch1"));
		}
예제 #16
0
		public void SingleMergeOnExcludedBranch_NoMergeFilledIn()
		{
			var commits = new List<Commit>()
			{
				new Commit("initial").WithRevision(m_file, "1.1"),
				new Commit("merge").WithRevision(m_file, "1.2", mergepoint: "1.1.2.1"),
			};

			var branchpoints = new Dictionary<string, Commit>()
			{
				{ "branch", commits[0] }
			};

			var streams = new BranchStreamCollection(commits, branchpoints);
			var resolver = new MergeResolver(m_logger, streams);
			resolver.Resolve();

			Assert.IsTrue(streams["MAIN"].ToList().All(c => c.MergeFrom == null));
		}
		public void OrderedBranches()
		{
			Commit subBranchPoint;
			m_commits.AddRange(new[]
			{
				new Commit("4").WithRevision(m_f1, "1.3"),
				new Commit("5").WithRevision(m_f1, "1.1.2.2"),
				subBranchPoint = new Commit("6").WithRevision(m_f1, "1.1.2.3"),
				new Commit("7").WithRevision(m_f1, "1.1.2.3.2.1"),
			});

			m_f1.WithBranch("subbranch", "1.1.2.3.0.2");
			m_branchpoints["subbranch"] = subBranchPoint;
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			var orderedBranches = streams.OrderedBranches.ToList();
			Assert.IsTrue(orderedBranches.SequenceEqual("MAIN", "branch", "subbranch"));
		}
		public void MoveCommit_FromStart()
		{
			m_commits.Add(new Commit("4").WithRevision(m_f1, "1.1.2.2"));
			m_commits.Add(new Commit("5").WithRevision(m_f1, "1.1.2.3"));
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			streams.MoveCommit(m_commits[1], m_commits[4]);

			Assert.IsTrue(streams["branch"].CommitId == "4");
			Assert.IsTrue(streams["branch"].ToList().Select(c => c.CommitId).SequenceEqual("4", "5", "2"));
			Assert.IsTrue(streams.Verify());
		}
		public void MoveCommit_ToEnd()
		{
			m_commits.Add(new Commit("4").WithRevision(m_f1, "1.3"));
			m_commits.Add(new Commit("5").WithRevision(m_f1, "1.4"));
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			streams.MoveCommit(m_commits[3], m_commits[4]);

			Assert.IsTrue(streams["MAIN"].ToList().Select(c => c.CommitId).SequenceEqual("1", "3", "5", "4"));
			Assert.IsTrue(streams.Head("MAIN").CommitId == "4");
			Assert.IsTrue(streams.Verify());
		}
예제 #20
0
		private void CreateHeadOnlyCommit(string branch, BranchStreamCollection streams, FileCollection allFiles, string branchMergeFrom)
		{
			var headOnlyState = m_headOnlyState[branch];
			var commitId = String.Format("headonly-{0}", branch);
			var commit = new Commit(commitId);

			var message = String.Format("Adding head-only files to {0}", m_branchRenamer.Process(branch));

			foreach (var file in headOnlyState.LiveFiles.OrderBy(i => i, StringComparer.OrdinalIgnoreCase))
			{
				var fileRevision = new FileRevision(allFiles[file], headOnlyState[file],
						mergepoint: Revision.Empty, time: DateTime.Now, author: "", commitId: commitId);
				fileRevision.AddMessage(message);
				commit.Add(fileRevision);
			}

			// check for a merge
			if (branchMergeFrom != null)
			{
				Commit mergeSource = streams.Head(branchMergeFrom);
				if (mergeSource.CommitId.StartsWith("headonly-"))
				{
					commit.MergeFrom = mergeSource;

					// check for deleted files
					var fileLookup = new HashSet<string>(commit.Select(r => r.File.Name));
					foreach (var r in mergeSource)
					{
						if (!fileLookup.Contains(r.File.Name))
						{
							var fileRevision = new FileRevision(
									file: r.File,
									revision: Revision.Empty,   // a bit lazy, but I think we can get away with it
									mergepoint: Revision.Empty,
									time: DateTime.Now,
									author: "",
									commitId: commitId,
									isDead: true);
							fileRevision.AddMessage(message);
							commit.Add(fileRevision);
						}
					}
				}
			}

			if (commit.Any())
			{
				m_log.WriteLine("Added commit {0}", commitId);
				streams.AppendCommit(commit);
			}
		}
		public void AppendCommit_ToBranch()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			var commit = new Commit("new").WithRevision(m_f1, "1.1.2.2");
			streams.AppendCommit(commit);

			Assert.AreSame(streams.Head("branch"), commit);
			Assert.AreSame(streams["branch"].Successor, commit);
			Assert.IsTrue(commit.Index > streams["MAIN"].Index, "Index set");
		}
예제 #22
0
		public MergeResolver(ILogger log, BranchStreamCollection streams)
		{
			m_log = log;
			m_streams = streams;
		}
예제 #23
0
		public void MergeFromParentBranch_Ignore()
		{
			var commits = new List<Commit>()
			{
				new Commit("initial").WithRevision(m_file, "1.1"),
				new Commit("branch1").WithRevision(m_file, "1.1.2.1"),
				new Commit("main1").WithRevision(m_file, "1.2"),
				new Commit("branch2").WithRevision(m_file, "1.1.2.2", mergepoint: "1.2"),
			};
			m_file.WithBranch("branch", "1.1.0.2");

			var branchpoints = new Dictionary<string, Commit>()
			{
				{ "branch", commits[0] }
			};

			var streams = new BranchStreamCollection(commits, branchpoints);
			var resolver = new MergeResolver(m_logger, streams);
			resolver.Resolve();

			Assert.IsTrue(streams["MAIN"].ToList().All(c => c.MergeFrom == null));
			Assert.IsTrue(streams["branch"].ToList().All(c => c.MergeFrom == null));
		}
예제 #24
0
 public MergeResolver(ILogger log, BranchStreamCollection streams)
 {
     m_log     = log;
     m_streams = streams;
 }
예제 #25
0
		private static void WriteBranchLogs(BranchStreamCollection streams)
		{
			foreach (var branch in streams.Branches)
			{
				var filename = String.Format("commits-{0}.log", branch);
				using (var writer = m_log.OpenDebugFile(filename))
				{
					writer.WriteLine("Branch: {0}", branch);
					writer.WriteLine();

					for (var c = streams[branch]; c != null; c = c.Successor)
						WriteCommitLog(writer, c);
				}
			}
		}
예제 #26
0
 public CommitPlayer(ILogger log, BranchStreamCollection streams)
 {
     m_log     = log;
     m_streams = streams;
 }
		public void Construct_BranchPredecessorSet()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsTrue(streams["branch"].ToList().Single().Predecessor == m_commits[0]);
		}
		public void MoveCommit_ToItself()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			streams.MoveCommit(m_commits[2], m_commits[2]);

			Assert.IsTrue(streams["MAIN"].ToList().SequenceEqual(m_commits[0], m_commits[2]));
			Assert.IsTrue(streams.Verify());
		}
예제 #29
0
		public void NestedBranches_Merges_OutOfOrder()
		{
			var now = DateTime.Now;
			var commits = CreateNestedBranches(true);
			var branchpoints = new Dictionary<string, Commit>()
			{
				{ "branch0", commits[0] },
				{ "branch1", commits[2] }
			};
			var branches = new BranchStreamCollection(commits, branchpoints);

			var player = new CommitPlayer(MockRepository.GenerateStub<ILogger>(), branches);
			var result = player.Play().Select(c => c.CommitId).ToList();

			Assert.IsTrue(result.SequenceEqual(new[] { "id0", "branch0_0", "branch1_0", "branch0_1", "id1" }));
		}
		public void MoveCommit_Backwards()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			streams.MoveCommit(m_commits[2], m_commits[1]);
		}
		public void Branches()
		{
			var streams = new BranchStreamCollection(m_commits, m_branchpoints);

			Assert.IsTrue(streams.Branches.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).SequenceEqual("branch", "MAIN"));
		}
예제 #32
0
		private List<string> SortBranches(IEnumerable<string> headOnlyBranches, BranchStreamCollection streams)
		{
			// build a set of branches that we care about
			var branches = new HashSet<string> { "MAIN" };
			foreach (var branch in headOnlyBranches)
				branches.Add(branch);

			// get a list of all branches in order and filter it
			var list = streams.OrderedBranches.Where(b => branches.Contains(b)).ToList();
			list.Reverse();
			return list;
		}
예제 #33
0
		private static void Analyse()
		{
			var parser = new CvsLogParser(m_config.Sandbox, m_config.CvsLogFileName, m_config.BranchMatcher);
			var builder = new CommitBuilder(m_log, parser.Parse());
			var exclusionFilter = new ExclusionFilter(m_log, m_config);

			IEnumerable<Commit> commits = builder.GetCommits()
					.SplitMultiBranchCommits()
					.FilterCommitsOnExcludedBranches()
					.FilterExcludedFiles(exclusionFilter)
					.AddCommitsToFiles()
					.Verify(m_log)
					.ToListIfNeeded();

			// build lookup of all files
			var allFiles = new FileCollection(parser.Files);
			var includedFiles = new FileCollection(parser.Files.Where(f => m_config.IncludeFile(f.Name)));

			WriteAllCommitsLog(commits);
			WriteExcludedFileLog(parser);

			var branchResolver = ResolveBranches(commits, includedFiles);
			commits = branchResolver.Commits;

			var tagResolver = ResolveTags(commits, includedFiles);
			commits = tagResolver.Commits;

			WriteTagLog("allbranches.log", branchResolver, parser.ExcludedBranches, m_config.BranchRename);
			WriteTagLog("alltags.log", tagResolver, parser.ExcludedTags, m_config.TagRename);
			WriteUserLog("allusers.log", commits);

			var streams = commits.SplitBranchStreams(branchResolver.ResolvedTags);

			// resolve merges
			var mergeResolver = new MergeResolver(m_log, streams);
			mergeResolver.Resolve();

			WriteBranchLogs(streams);

			// add any "head-only" files
			exclusionFilter.CreateHeadOnlyCommits(m_config.HeadOnlyBranches, streams, allFiles);

			// store data needed for import
			m_streams = streams;
		}
예제 #34
0
		public CommitPlayer(ILogger log, BranchStreamCollection streams)
		{
			m_log = log;
			m_streams = streams;
		}