示例#1
0
        public void CanGetHeadTipIdSha()
        {
            var headTipIdSha = vSut.HeadTipIdSha(MasterFolder);

            Assert.IsFalse(string.IsNullOrEmpty(headTipIdSha));
            Assert.IsTrue(headTipIdSha.Length >= 40);
        }
示例#2
0
        public async Task <YesNoInconclusive> UpdateNugetPackagesInRepositoryAsync(IFolder repositoryFolder, IErrorsAndInfos errorsAndInfos)
        {
            using (SimpleLogger.BeginScope(SimpleLoggingScopeId.Create(nameof(UpdateNugetPackagesInRepositoryAsync), Guid.NewGuid().ToString()))) {
                SimpleLogger.LogInformation("Determining files with uncommitted changes");
                var yesNoInconclusive = new YesNoInconclusive();
                var files             = GitUtilities.FilesWithUncommittedChanges(repositoryFolder);
                yesNoInconclusive.Inconclusive = files.Any(f => EndingsThatAllowReset.All(e => !f.EndsWith("." + e, StringComparison.InvariantCultureIgnoreCase)));
                yesNoInconclusive.YesNo        = false;
                if (yesNoInconclusive.Inconclusive)
                {
                    errorsAndInfos.Infos.Add("Not all files allow a reset");
                    SimpleLogger.LogInformation($"Returning {yesNoInconclusive}");
                    return(yesNoInconclusive);
                }

                SimpleLogger.LogInformation("Resetting repository");
                GitUtilities.Reset(repositoryFolder, GitUtilities.HeadTipIdSha(repositoryFolder), errorsAndInfos);
                if (errorsAndInfos.AnyErrors())
                {
                    errorsAndInfos.Infos.Add("Could not reset");
                    SimpleLogger.LogInformation($"Returning {yesNoInconclusive}");
                    return(yesNoInconclusive);
                }

                SimpleLogger.LogInformation("Searching for project files");
                var projectFileFullNames = Directory.GetFiles(repositoryFolder.SubFolder("src").FullName, "*.csproj", SearchOption.AllDirectories).ToList();
                if (!projectFileFullNames.Any())
                {
                    errorsAndInfos.Infos.Add("No project files found");
                    SimpleLogger.LogInformation($"Returning {yesNoInconclusive}");
                    return(yesNoInconclusive);
                }

                foreach (var projectFileFullName in projectFileFullNames)
                {
                    SimpleLogger.LogInformation($"Analyzing project file {projectFileFullName}");
                    var projectErrorsAndInfos = new ErrorsAndInfos();
                    if (!await UpdateNugetPackagesForProjectAsync(projectFileFullName, yesNoInconclusive.YesNo, projectErrorsAndInfos))
                    {
                        continue;
                    }

                    yesNoInconclusive.YesNo = true;
                }

                if (yesNoInconclusive.YesNo)
                {
                    errorsAndInfos.Infos.Add("No project was updated");
                    SimpleLogger.LogInformation($"Returning {yesNoInconclusive}");
                    return(yesNoInconclusive);
                }

                SimpleLogger.LogInformation("Resetting repository");
                GitUtilities.Reset(repositoryFolder, GitUtilities.HeadTipIdSha(repositoryFolder), errorsAndInfos);
                SimpleLogger.LogInformation($"Returning {yesNoInconclusive}");
                return(yesNoInconclusive);
            }
        }
示例#3
0
        public async Task <bool> HasPullRequestForThisBranchAndItsHeadTipAsync(IFolder repositoryFolder, IErrorsAndInfos errorsAndInfos)
        {
            var pullRequests = await GetPullRequestsAsync(repositoryFolder, "all", errorsAndInfos);

            var checkedOutBranch = vGitUtilities.CheckedOutBranch(repositoryFolder);
            var headTipIdSha     = vGitUtilities.HeadTipIdSha(repositoryFolder);

            return(pullRequests.Any(p => p.Branch == checkedOutBranch && p.Sha == headTipIdSha));
        }
示例#4
0
        private async Task AutoCommitAndPushAsync(string nugetFeedId, IFolder repositoryFolder, List <string> files, bool onlyIfNecessary, string commitMessage, bool noRebuildRequired, IErrorsAndInfos errorsAndInfos)
        {
            var branchName = GitUtilities.CheckedOutBranch(repositoryFolder);

            if (branchName != "master")
            {
                errorsAndInfos.Errors.Add(Properties.Resources.CheckedOutBranchIsNotMaster);
                return;
            }

            var headTipShaBeforePush = GitUtilities.HeadTipIdSha(repositoryFolder);

            GitUtilities.IdentifyOwnerAndName(repositoryFolder, out var owner, out _, errorsAndInfos);
            if (errorsAndInfos.AnyErrors())
            {
                errorsAndInfos.Errors.Add(Properties.Resources.OwnerAndNameNotFound);
                return;
            }

            var personalAccessTokensSecret = new PersonalAccessTokensSecret();
            var personalAccessTokens       = await SecretRepository.GetAsync(personalAccessTokensSecret, errorsAndInfos);

            var personalAccessToken = personalAccessTokens.FirstOrDefault(t => t.Owner == owner && t.Purpose == "AutoCommitPush");

            if (personalAccessToken == null)
            {
                errorsAndInfos.Errors.Add(Properties.Resources.AutoCommitPushAccessTokenNotFound);
                return;
            }

            using var repo = new Repository(repositoryFolder.FullName);

            var remotes = repo.Network.Remotes.ToList();

            if (remotes.Count != 1)
            {
                errorsAndInfos.Errors.Add(Properties.Resources.RemoteNotFoundOrNotUnique);
                return;
            }

            var remote = remotes[0];

            files.ForEach(f => {
                // ReSharper disable once AccessToDisposedClosure
                Commands.Stage(repo, f);
            });

            var checkFiles = GitUtilities.FilesWithUncommittedChanges(repositoryFolder);

            if (onlyIfNecessary && !checkFiles.Any())
            {
                return;
            }

            if (checkFiles.Count != files.Count)
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.NumberOfFilesWithUncommittedChangesHasChanged,
                                                        string.Join(", ", files), string.Join(", ", checkFiles)));
                return;
            }

            var author    = new Signature(personalAccessToken.TokenName, personalAccessToken.Email, DateTime.Now);
            var committer = author;

            repo.Commit(commitMessage, author, committer);

            var options = new PushOptions {
                CredentialsProvider = (_, _, _) => new UsernamePasswordCredentials {
                    Username = owner,
                    Password = personalAccessToken.Token
                }
            };

            repo.Network.Push(remote, @"refs/heads/" + branchName, options);

            if (!noRebuildRequired)
            {
                return;
            }

            var pushedHeadTipShaRepository = PushedHeadTipShaRepository;

            if (!(await pushedHeadTipShaRepository.GetAsync(nugetFeedId, errorsAndInfos)).Contains(headTipShaBeforePush))
            {
                return;
            }

            var headTipSha = GitUtilities.HeadTipIdSha(repositoryFolder);
            await pushedHeadTipShaRepository.AddAsync(nugetFeedId, headTipSha, errorsAndInfos);
        }
        public async Task <IPackageToPush> FindPackageToPushAsync(string nugetFeedId, IFolder packageFolderWithBinaries, IFolder repositoryFolder, string solutionFileFullName, IErrorsAndInfos errorsAndInfos)
        {
            IPackageToPush packageToPush = new PackageToPush();

            errorsAndInfos.Infos.Add(Properties.Resources.CheckingProjectVsSolution);
            var projectFileFullName = solutionFileFullName.Replace(".sln", ".csproj");

            if (!File.Exists(projectFileFullName))
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.ProjectFileNotFound, projectFileFullName));
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.LoadingProject);
            var project = ProjectFactory.Load(solutionFileFullName, projectFileFullName, errorsAndInfos);

            if (errorsAndInfos.Errors.Any())
            {
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.LoadingNugetFeeds);
            var developerSettingsSecret = new DeveloperSettingsSecret();
            var developerSettings       = await SecretRepository.GetAsync(developerSettingsSecret, errorsAndInfos);

            if (errorsAndInfos.Errors.Any())
            {
                return(packageToPush);
            }

            if (developerSettings == null)
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.MissingDeveloperSettings, developerSettingsSecret.Guid + ".xml"));
                return(packageToPush);
            }

            var nugetFeedsSecret = new SecretNugetFeeds();
            var nugetFeeds       = await SecretRepository.GetAsync(nugetFeedsSecret, errorsAndInfos);

            if (errorsAndInfos.AnyErrors())
            {
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.IdentifyingNugetFeed);
            var nugetFeed = nugetFeeds.FirstOrDefault(f => f.Id == nugetFeedId);

            if (nugetFeed == null)
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.UnknownNugetFeed, nugetFeedId, nugetFeedsSecret.Guid + ".xml"));
                return(packageToPush);
            }

            if (!nugetFeed.IsAFolderToResolve())
            {
                var nugetConfigFileFullName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\NuGet\" + "nuget.config";
                packageToPush.ApiKey = NugetConfigReader.GetApiKey(nugetConfigFileFullName, nugetFeed.Id, errorsAndInfos);
                if (errorsAndInfos.Errors.Any())
                {
                    return(packageToPush);
                }
            }

            errorsAndInfos.Infos.Add(Properties.Resources.IdentifyingFeedUrl);
            var source = await nugetFeed.UrlOrResolvedFolderAsync(FolderResolver, errorsAndInfos);

            if (errorsAndInfos.AnyErrors())
            {
                return(packageToPush);
            }

            packageToPush.FeedUrl = source;
            if (string.IsNullOrEmpty(packageToPush.FeedUrl))
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.IncompleteDeveloperSettings, developerSettingsSecret.Guid + ".xml"));
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.SearchingLocalPackage);
            var localPackageRepository = new FindLocalPackagesResourceV2(packageFolderWithBinaries.FullName);
            var localPackages          = localPackageRepository.GetPackages(new NullLogger(), CancellationToken.None).Where(p => !p.Identity.Version.IsPrerelease).ToList();

            if (!localPackages.Any())
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.NoPackageFilesFound, packageFolderWithBinaries.FullName));
                return(packageToPush);
            }

            var latestLocalPackageVersion = localPackages.Max(p => p.Identity.Version.Version);

            errorsAndInfos.Infos.Add(string.Format(Properties.Resources.FoundLocalPackage, latestLocalPackageVersion));

            errorsAndInfos.Infos.Add(Properties.Resources.SearchingRemotePackage);
            var packageId      = string.IsNullOrWhiteSpace(project.PackageId) ? project.RootNamespace : project.PackageId;
            var remotePackages = await NugetFeedLister.ListReleasedPackagesAsync(nugetFeedId, packageId, errorsAndInfos);

            if (errorsAndInfos.Errors.Any())
            {
                return(packageToPush);
            }
            if (!remotePackages.Any())
            {
                errorsAndInfos.Errors.Add(string.Format(Properties.Resources.NoRemotePackageFilesFound, packageToPush.FeedUrl, packageId));
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.LoadingPushedHeadTipShas);
            var pushedHeadTipShas = await PushedHeadTipShaRepository.GetAsync(nugetFeedId, errorsAndInfos);

            if (errorsAndInfos.AnyErrors())
            {
                return(packageToPush);
            }

            var headTipIdSha = repositoryFolder == null ? "" : GitUtilities.HeadTipIdSha(repositoryFolder);

            if (!string.IsNullOrWhiteSpace(headTipIdSha) && pushedHeadTipShas.Contains(headTipIdSha))
            {
                errorsAndInfos.Infos.Add(string.Format(Properties.Resources.HeadTipShaHasAlreadyBeenPushed, headTipIdSha, nugetFeedId));
                return(packageToPush);
            }

            var latestRemotePackageVersion = remotePackages.Max(p => p.Identity.Version.Version);

            errorsAndInfos.Infos.Add(string.Format(Properties.Resources.FoundRemotePackage, latestRemotePackageVersion));
            if (latestRemotePackageVersion >= latestLocalPackageVersion)
            {
                errorsAndInfos.Infos.Add(string.Format(Properties.Resources.RemotePackageHasHigherOrEqualVersion, headTipIdSha));
                return(packageToPush);
            }

            errorsAndInfos.Infos.Add(Properties.Resources.CheckingRemotePackageTag);
            var remotePackage = remotePackages.First(p => p.Identity.Version.Version == latestRemotePackageVersion);

            if (!string.IsNullOrEmpty(remotePackage.Tags) && !string.IsNullOrWhiteSpace(headTipIdSha))
            {
                errorsAndInfos.Infos.Add(string.Format(Properties.Resources.TagsAre, remotePackage.Tags));
                var tags = remotePackage.Tags.Split(' ').ToList();
                if (tags.Contains(headTipIdSha))
                {
                    errorsAndInfos.Infos.Add(string.Format(Properties.Resources.PackageAlreadyTaggedWithHeadTipSha, headTipIdSha));
                    return(packageToPush);
                }

                if (tags.Count != 1)
                {
                    errorsAndInfos.Errors.Add(string.Format(Properties.Resources.RemotePackageContainsSeveralTags, tags));
                    return(packageToPush);
                }

                var tag = tags[0];
                errorsAndInfos.Infos.Add(string.Format(Properties.Resources.CheckingIfThereAreChangedBinaries, headTipIdSha, tag));
                var listerErrorsAndInfos = new ErrorsAndInfos();
                var changedBinaries      = ChangedBinariesLister.ListChangedBinaries(packageId, headTipIdSha, tag, listerErrorsAndInfos);
                if (listerErrorsAndInfos.AnyErrors())
                {
                    errorsAndInfos.Infos.AddRange(listerErrorsAndInfos.Infos);
                    errorsAndInfos.Errors.AddRange(listerErrorsAndInfos.Errors);
                    return(packageToPush);
                }
                if (!changedBinaries.Any())
                {
                    errorsAndInfos.Infos.Add(string.Format(Properties.Resources.NoBinariesHaveChanged));
                    return(packageToPush);
                }
            }

            errorsAndInfos.Infos.Add(Properties.Resources.PackageNeedsToBePushed);
            packageToPush.PackageFileFullName = packageFolderWithBinaries.FullName + @"\" + packageId + "." + latestLocalPackageVersion + ".nupkg";
            packageToPush.Id      = packageId;
            packageToPush.Version = latestLocalPackageVersion?.ToString();
            if (File.Exists(packageToPush.PackageFileFullName))
            {
                return(packageToPush);
            }

            errorsAndInfos.Errors.Add(string.Format(Properties.Resources.FileNotFound, packageToPush.PackageFileFullName));
            return(packageToPush);
        }