void Add(Parts destination, Parts source, int level) { var s = destination.SegmentPartsByNestingLevel(level); if (destination.NumberOfPathSegments == level + 1) { var Leaf = new Tuple<Parts, Parts>(destination, source); LeavesToCreate.Add(s.Name, Leaf); return; } TargetTree sb; if (!SubTreesToUpdate.TryGetValue(s.Name, out sb)) { sb = new TargetTree(s); SubTreesToUpdate.Add(s.Name, sb); } sb.Add(destination, source, ++level); }
public IEnumerable<string> Sync(Diff diff, SyncOutput expectedOutput, IEnumerable<string> labelsToApplyOnPullRequests = null) { var labels = labelsToApplyOnPullRequests == null ? new string[]{ } : labelsToApplyOnPullRequests.ToArray(); if (labels.Any() && expectedOutput != SyncOutput.CreatePullRequest) { throw new InvalidOperationException(string.Format("Labels can only be applied in '{0}' mode.", SyncOutput.CreatePullRequest)); } var t = diff.Transpose(); var branchName = "SyncOMatic-" + DateTimeOffset.UtcNow.ToString("yyyyMMdd-HHmmss"); foreach (var updatesPerOwnerRepositoryBranch in t.Values) { var root = updatesPerOwnerRepositoryBranch.First().Item1.RootTreePart; var tt = new TargetTree(root); foreach (var change in updatesPerOwnerRepositoryBranch) { var source = change.Item2; var destination = change.Item1; tt.Add(destination, source); } var btt = BuildTargetTree(tt); var parentCommit = gw.RootCommitFrom(root); var c = gw.CreateCommit(btt, root.Owner, root.Repository, parentCommit.Sha); switch (expectedOutput) { case SyncOutput.CreateCommit: yield return "https://github.com/" + root.Owner + "/" + root.Repository + "/commit/" + c; break; case SyncOutput.CreateBranch: branchName = gw.CreateBranch(root.Owner, root.Repository, branchName, c); yield return "https://github.com/" + root.Owner + "/" + root.Repository + "/compare/" + UrlSanitize(root.Branch) + "..." + UrlSanitize(branchName); break; case SyncOutput.CreatePullRequest: branchName = gw.CreateBranch(root.Owner, root.Repository, branchName, c); var prNumber = gw.CreatePullRequest(root.Owner, root.Repository, branchName, root.Branch); gw.ApplyLabels(root.Owner, root.Repository, prNumber, labels); yield return "https://github.com/" + root.Owner + "/" + root.Repository + "/pull/" + prNumber; break; default: throw new NotSupportedException(); } } }
string BuildTargetTree(TargetTree tt) { var treeFrom = gw.TreeFrom(tt.Current, false); NewTree newTree; if (treeFrom != null) { var destinationParentTree = treeFrom.Item2; newTree = BuildNewTreeFrom(destinationParentTree); } else { newTree = new NewTree(); } foreach (var st in tt.SubTreesToUpdate.Values) { RemoveTreeItemFrom(newTree, st.Current.Name); var sha = BuildTargetTree(st); newTree.Tree.Add(new NewTreeItem { Mode = "040000", Path = st.Current.Name, Sha = sha, Type = TreeType.Tree }); } foreach (var l in tt.LeavesToCreate.Values) { var destination = l.Item1; var source = l.Item2; RemoveTreeItemFrom(newTree, destination.Name); SyncLeaf(source, destination); switch (source.Type) { case TreeEntryTargetType.Blob: var sourceBlobItem = gw.BlobFrom(source, true).Item2; newTree.Tree.Add(new NewTreeItem { Mode = sourceBlobItem.Mode, Path = destination.Name, Sha = source.Sha, Type = TreeType.Blob }); break; case TreeEntryTargetType.Tree: newTree.Tree.Add(new NewTreeItem { Mode = "040000", Path = destination.Name, Sha = source.Sha, Type = TreeType.Tree }); break; default: throw new NotSupportedException(); } } return gw.CreateTree(newTree, tt.Current.Owner, tt.Current.Repository); }