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")); }
/// <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]); }
/// <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()); }
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); }
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); }
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); } }
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; }
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); } } } }
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); }
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)); }
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")); }
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()); }
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"); }
public MergeResolver(ILogger log, BranchStreamCollection streams) { m_log = log; m_streams = streams; }
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)); }
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); } } }
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()); }
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")); }
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; }
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; }