public Revision Read(List <string> branches, long revision) { branches = branches.ToList(); var data = new Revision(); var args = new SvnLogArgs { Start = new SvnRevision(revision), End = new SvnRevision(revision) }; Collection <SvnLogEventArgs> items; try { var client = _client.GetObject(); client.GetLog(_svnPath, args, out items); _client.PutObject(client); } catch (SvnFileSystemException e) { if (e.SvnErrorCode == SvnErrorCode.SVN_ERR_FS_NO_SUCH_REVISION) { return(null); } throw; } data.Author = items[0].Author; data.Message = items[0].LogMessage; data.Time = items[0].Time; if (items[0].ChangedPaths == null) { return(data); } foreach (var path in items[0].ChangedPaths) { string branch; RevisionAction action = null; if (path.NodeKind == SvnNodeKind.Directory && path.CopyFromPath != null) { branch = branches.SingleOrDefault(a => path.CopyFromPath.Remove(0, 1) == a); if (branch != null) { if (!branches.Any(a => path.Path.Remove(0, 1).StartsWith(a + "/"))) { var value = GetBranchData(data.Data, path.Path.Remove(0, 1)); value.CreateBranchFrom = path.CopyFromPath.Remove(0, 1); value.CreateBranchFromRevision = path.CopyFromRevision; branches.Add(path.Path.Remove(0, 1)); continue; } } branch = branches.SingleOrDefault(a => a.StartsWith(path.Path.Remove(0, 1) + "/")); if (branch != null) { var value = GetBranchData(data.Data, branch); value.ParentRenameFrom = path.CopyFromPath.Remove(0, 1); value.ParentRenameFromRevision = path.CopyFromRevision; value.ParentRenameTo = path.Path.Remove(0, 1); continue; } } branch = branches.SingleOrDefault(a => path.Path.Remove(0, 1).StartsWith(a + "/") || path.Path.Remove(0, 1) == a); if (branch == null) { continue; } GetBranchData(data.Data, branch); if (path.Path.Remove(0, 1) == branch && path.Action != SvnChangeAction.Delete) { var targetNew = new SvnUriTarget(new Uri(_svnPath, path.Path.Remove(0, 1)), revision); var client = _client.GetObject(); client.GetAppliedMergeInfo(targetNew, new SvnGetAppliedMergeInfoArgs() { }, out var infoNew); if (infoNew != null && infoNew.AppliedMerges.Count > 0) { var targetOld = new SvnUriTarget(new Uri(_svnPath, path.Path.Remove(0, 1)), revision - 1); client.GetAppliedMergeInfo(targetOld, new SvnGetAppliedMergeInfoArgs() { }, out var infoOld); foreach (var merge in infoNew.AppliedMerges) { var p = merge.Uri.AbsoluteUri.Remove(0, _svnPath.AbsoluteUri.Length); if (branches.Contains(p)) { var haveMerges = false; foreach (var range in merge.MergeRanges) { if (infoOld != null && infoOld.AppliedMerges.Any(a => a.Uri == merge.Uri && a.MergeRanges.Any(b => b.Start == range.Start && b.End == range.End))) { continue; } haveMerges = true; /*var d = GetBranchData(data.Data, branch); * if (!d.Merges.TryGetValue(p, out var v)) * { * v = new List<Tuple<long, long>>(); * d.Merges[p] = v; * } * * v.Add(Tuple.Create(range.Start + 1, range.End));*/ } if (haveMerges) { var source = new SvnUriTarget(new Uri(_svnPath, p), revision); client.GetMergesEligible(targetOld, source, new SvnMergesEligibleArgs() { Depth = SvnDepth.Empty }, out var listOld); client.GetMergesEligible(targetNew, source, new SvnMergesEligibleArgs() { Depth = SvnDepth.Empty }, out var listNew); var merged = listOld.Where(a => listNew.All(b => a.Revision != b.Revision)).Select(a => a.Revision).OrderBy(a => a).ToList(); var notMerged = listNew.Select(a => a.Revision).OrderBy(a => a).ToList(); if (merged.Count > 0) { var d = GetBranchData(data.Data, branch); d.Merges[p] = new Tuple <List <long>, List <long> >(merged, notMerged); } } } } } _client.PutObject(client); } var gitPath = path.Path.Remove(0, branch.Length + 1); if (gitPath.Length > 0) { gitPath = gitPath.Remove(0, 1); } action = new RevisionAction { GitPath = gitPath, SvnPath = path.Path.Remove(0, 1) }; if (path.CopyFromPath != null && action.GitPath == "") { var d = GetBranchData(data.Data, branch); d.CreateBranchFrom = path.CopyFromPath.Remove(0, 1); d.CreateBranchFromRevision = path.CopyFromRevision; continue; } /*if (path.CopyFromPath != null && (!path.CopyFromPath.Remove(0, 1).StartsWith(branch))) * throw new NotImplementedException();*/ switch (path.NodeKind) { case SvnNodeKind.File: switch (path.Action) { case SvnChangeAction.Add: action.Type = ActionType.AddFile; break; case SvnChangeAction.Replace: case SvnChangeAction.Modify: action.Type = ActionType.EditFile; break; case SvnChangeAction.Delete: action.Type = ActionType.RemoveFile; break; default: throw new NotImplementedException(); } break; case SvnNodeKind.Directory: switch (path.Action) { case SvnChangeAction.Delete: case SvnChangeAction.Replace: if (action.GitPath == "") { var value = GetBranchData(data.Data, branch); value.RemoveBranch = true; action = null; } else { action.Type = ActionType.RemoveDir; } if (path.Action == SvnChangeAction.Replace) { goto add; } break; case SvnChangeAction.Add: add: if (path.CopyFromPath != null) { var b = branches.SingleOrDefault(a => path.CopyFromPath.Remove(0, 1).StartsWith(a)); if (b != null) { action.Type = ActionType.CopyDir; action.FromPath = b == path.CopyFromPath.Remove(0, 1) ? "" : path.CopyFromPath.Remove(0, b.Length + 2); action.FromRevision = path.CopyFromRevision; action.Branch = b; } else { action.Type = ActionType.CopyDirFromExternal; action.FromPath = path.CopyFromPath.Remove(0, 1); action.FromRevision = path.CopyFromRevision; } } else if (path.Action != SvnChangeAction.Replace) { action = null; } break; case SvnChangeAction.Modify: action = null; break; default: throw new NotImplementedException(); } break; } if (action != null) { Add(data.Data, branch, action); } } return(data); }
private void Add(Dictionary <string, BranchData> data, string branch, RevisionAction action) { var value = GetBranchData(data, branch); value.Data.Add(action); }