Example #1
0
    void PerformRepoSync(Syncer som, string repoName, string defaultBranch, string srcRoot, string solutionName, List<SyncItem> itemsToSync)
    {
        if (itemsToSync == null)
        {
            itemsToSync = DefaultTemplateRepo.ItemsToSync;
        }

        if (solutionName == null)
        {
            solutionName = repoName;
        }

        var toSync = new RepoToSync
        {
            Name = repoName,
            Branch = defaultBranch,
            SolutionName = solutionName,
            SrcRoot = srcRoot
        };

        var diff = som.Diff(toSync.GetMapper(itemsToSync));
        Assert.NotNull(diff);

        var createdSyncBranch = som.Sync(diff, SyncOutput.CreatePullRequest, new[] { "Internal refactoring" }).FirstOrDefault();

        if (string.IsNullOrEmpty(createdSyncBranch))
        {
            Console.Out.WriteLine("Repo {0} is in sync", repoName);
        }
        else
        {
            Console.Out.WriteLine("Pull created for {0}, click here to review and pull: {1}", repoName, createdSyncBranch);
        }
    }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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"}");
            }
        }