public void Sync() { using (var syncer = new Syncer(GetCredentials(), null, ConsoleLogger)) { foreach (var map in Mapper()) { var diff = syncer.Diff(map); foreach (var output in syncer.Sync(diff, SyncOutput.CreatePullRequest)) { if (!string.IsNullOrEmpty(output)) { Console.Out.WriteLine("Done " + output); } } } } }
public async Task <SyncContext> CalculateSyncContext(RepositoryInfo targetRepository) { var syncContext = new SyncContext(targetRepository); using (var syncer = new Syncer(targetRepository.Credentials, null, log)) { var diffs = new List <Mapper>(); var includedPaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); var descriptionBuilder = new StringBuilder(); descriptionBuilder.AppendLine("This is an automated synchronization PR."); descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine("The following source template repositories were used:"); // Note: iterate backwards, later registered sources should override earlier registrations for (var i = sources.Count - 1; i >= 0; i--) { var sourceRepository = sources[i]; var sourceRepositoryDisplayName = $"{sourceRepository.Owner}/{sourceRepository.Repository}"; var itemsToSync = new List <SyncItem>(); foreach (var item in await OctokitEx.GetRecursive(sourceRepository.Credentials, sourceRepository.Owner, sourceRepository.Repository)) { if (includedPaths.Contains(item)) { continue; } includedPaths.Add(item); if (manualSyncItems.Any(x => item.StartsWith(x.Path, StringComparison.OrdinalIgnoreCase))) { switch (syncMode) { case SyncMode.IncludeAllByDefault: // Continue break; case SyncMode.ExcludeAllByDefault: // Ignore this file continue; default: throw new ArgumentOutOfRangeException(nameof(syncMode), $"Sync mode '{syncMode}' is not supported"); } } itemsToSync.Add(new SyncItem { Parts = new Parts($"{sourceRepository.Owner}/{sourceRepository.Repository}", TreeEntryTargetType.Blob, sourceRepository.Branch, item), ToBeAdded = true, Target = null }); } var targetRepositoryToSync = new RepoToSync { Owner = targetRepository.Owner, Repo = targetRepository.Repository, TargetBranch = targetRepository.Branch }; var sourceMapper = targetRepositoryToSync.GetMapper(itemsToSync); var diff = await syncer.Diff(sourceMapper); if (diff.ToBeAddedOrUpdatedEntries.Count() > 0 || diff.ToBeRemovedEntries.Count() > 0) { diffs.Add(diff); descriptionBuilder.AppendLine($"* {sourceRepositoryDisplayName}"); } } var finalDiff = new Mapper(); foreach (var diff in diffs) { foreach (var item in diff.ToBeAddedOrUpdatedEntries) { foreach (var value in item.Value) { log($"Mapping '{item.Key.Url}' => '{value.Url}'"); finalDiff.Add(item.Key, value); } } // Note: how to deal with items to be removed } syncContext.Diff = finalDiff; syncContext.Description = descriptionBuilder.ToString(); } return(syncContext); }
public async Task <SyncContext> CalculateSyncContext(RepositoryInfo targetRepository) { var syncContext = new SyncContext(targetRepository); using (var syncer = new Syncer(targetRepository.Credentials, null, log)) { var diffs = new List <Mapper>(); var includedPaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); var descriptionBuilder = new StringBuilder(); descriptionBuilder.AppendLine("This is an automated synchronization PR."); descriptionBuilder.AppendLine(); descriptionBuilder.AppendLine("The following source template repositories were used:"); // Note: iterate backwards, later registered sources should override earlier registrations for (var i = sources.Count - 1; i >= 0; i--) { var source = sources[i]; var displayName = $"{source.Owner}/{source.Repository}"; var itemsToSync = new List <SyncItem>(); foreach (var item in await OctokitEx.GetRecursive(source.Credentials, source.Owner, source.Repository, null, source.Branch)) { if (includedPaths.Contains(item)) { continue; } includedPaths.Add(item); ProcessItem(item, itemsToSync, source); } var targetRepositoryToSync = new RepoToSync { Owner = targetRepository.Owner, Repo = targetRepository.Repository, TargetBranch = targetRepository.Branch }; var sourceMapper = targetRepositoryToSync.GetMapper(itemsToSync); var diff = await syncer.Diff(sourceMapper); if (diff.ToBeAddedOrUpdatedEntries.Any() || diff.ToBeRemovedEntries.Any()) { diffs.Add(diff); descriptionBuilder.AppendLine($"* {displayName}"); } } var finalDiff = new Mapper(); foreach (var diff in diffs) { foreach (var item in diff.ToBeAddedOrUpdatedEntries) { foreach (var value in item.Value) { log($"Mapping '{item.Key.Url}' => '{value.Url}'"); finalDiff.Add(item.Key, value); } } // Note: how to deal with items to be removed } syncContext.Diff = finalDiff; syncContext.Description = descriptionBuilder.ToString(); } return(syncContext); }
public override async Task Execute(string[] parameters, IResponse response) { var branchName = parameters[3]; var ghRepo = await GitHubClientBuilder.Build().Repository.Get("Particular", parameters[1]); //we need the exact name since the sync is case sensitive for eg. the .dotSettings file var repoName = ghRepo.Name; await response.Send($"Got it! Initiating a sync for {repoName}/{branchName}"); using (var som = new Syncer(GitHubHelper.Credentials, null, logEntry => { //no-op logging for low, until we figure out log channels })) { var toSync = new RepoToSync { Name = repoName, Branch = branchName, SolutionName = repoName, SrcRoot = "src" }; var diff = som.Diff(toSync.GetMapper(DefaultTemplateRepo.ItemsToSync)); ExceptionDispatchInfo capturedException = null; try { await diff; var sync = som.Sync(diff.Result, SyncOutput.CreatePullRequest, new[] { ClassificationLabels.RefactoringLabelName, }); await sync; var createdSyncBranch = sync.Result.FirstOrDefault(); if (string.IsNullOrEmpty(createdSyncBranch)) { await response.Send($"Repo {repoName} is already in sync, nothing for me to do!"); } else { await response.Send($"Pull created for {repoName}, click here to review and pull: {createdSyncBranch}"); } } catch (AggregateException aggEx) { var ex = aggEx.Flatten().InnerException; if (ex is Octokit.NotFoundException) { // The github api is weird. NotFound is actually a // permission error. capturedException = ExceptionDispatchInfo.Capture(ex); } } catch (Octokit.NotFoundException ex) { // The github api is weird. NotFound is actually a // permission error. capturedException = ExceptionDispatchInfo.Capture(ex); } if (capturedException != null) { await response.Send($"I do not have commit access to repo {repoName}. Please add 'particularbot' to the list of contributers."); //capturedException.Throw(); } await response.Send($"Want to know more about repo syncing? Go here: {"https://github.com/Particular/PlatformDevelopment/wiki/Repository%20synchronisation"}"); } }