Esempio n. 1
0
        public static GitTreeWriter AsWriter(this GitTree tree)
        {
            if (tree is null)
            {
                throw new ArgumentNullException(nameof(tree));
            }

            var gtw = GitTreeWriter.CreateEmpty();

            foreach (var v in tree)
            {
                switch (v.ElementType)
                {
                case GitTreeElementType.File:
                case GitTreeElementType.FileExecutable:
                case GitTreeElementType.Directory:
                    gtw.Add(v.Name, v.GitObject.AsLazy());
                    break;

                case GitTreeElementType.SymbolicLink:
                case GitTreeElementType.GitCommitLink:
                    throw new NotImplementedException();
                }
            }
            gtw.PutId(tree.Id); // TODO: Cleanup
            return(gtw);
        }
Esempio n. 2
0
        internal GitTreeItemCollection(GitTree gitTree, bool justFiles)
            : base(gitTree?.Repository ?? throw new ArgumentNullException(nameof(gitTree)))
        {
            if (gitTree is null)
            {
                throw new ArgumentNullException(nameof(gitTree));
            }

            _gitTree   = gitTree;
            _justFiles = justFiles;
        }
Esempio n. 3
0
        private static async Task CreatePullRequestAsync(GitHubClient client, GitRepo gitRepo, Config config)
        {
            GitHubProject project       = new GitHubProject(gitRepo.Name, gitRepo.Owner);
            GitHubProject forkedProject = new GitHubProject(gitRepo.Name, Options.GitUser);
            GitHubBranch  baseBranch    = new GitHubBranch(gitRepo.Branch, project);
            GitHubBranch  headBranch    = new GitHubBranch(
                $"{gitRepo.Name}-{gitRepo.Branch}{config.WorkingBranchSuffix}",
                forkedProject);

            IEnumerable <GitObject> changes = await GetUpdatedFiles(config.SourcePath, client, baseBranch);

            if (!changes.Any())
            {
                return;
            }

            GitReference currentRef = await client.GetReferenceAsync(project, $"heads/{baseBranch.Name}");

            string  parentSha = currentRef.Object.Sha;
            GitTree tree      = await client.PostTreeAsync(forkedProject, parentSha, changes.ToArray());

            GitCommit commit = await client.PostCommitAsync(forkedProject, config.CommitMessage, tree.Sha, new[] { parentSha });

            string workingReference = $"heads/{headBranch.Name}";

            if (await BranchExists(client, forkedProject, workingReference))
            {
                await client.PatchReferenceAsync(forkedProject, workingReference, commit.Sha, force : true);
            }
            else
            {
                await client.PostReferenceAsync(forkedProject, workingReference, commit.Sha);
            }

            GitHubPullRequest pullRequestToUpdate = await client.SearchPullRequestsAsync(
                project,
                headBranch.Name,
                await client.GetMyAuthorIdAsync());

            if (pullRequestToUpdate == null)
            {
                await client.PostGitHubPullRequestAsync(
                    $"[{gitRepo.Branch}] {config.PullRequestTitle}",
                    config.PullRequestDescription,
                    headBranch,
                    baseBranch,
                    maintainersCanModify : true);
            }
        }
        public override async Task ExecuteAsync()
        {
            Logger.WriteHeading("UPDATING VERSIONS");

            // Hookup a TraceListener in order to capture details from Microsoft.DotNet.VersionTools
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

            DockerHelper.PullBaseImages(Manifest, Options);

            GitHubAuth githubAuth = new GitHubAuth(Options.GitAuthToken, Options.GitUsername, Options.GitEmail);

            using (GitHubClient client = new GitHubClient(githubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        GitHubProject project    = new GitHubProject(Options.GitRepo, Options.GitOwner);
                        GitHubBranch  branch     = new GitHubBranch(Options.GitBranch, project);
                        GitObject[]   gitObjects = await GetUpdatedVerionInfo(client, branch);

                        if (gitObjects.Any())
                        {
                            string       masterRef     = $"heads/{Options.GitBranch}";
                            GitReference currentMaster = await client.GetReferenceAsync(project, masterRef);

                            string  masterSha = currentMaster.Object.Sha;
                            GitTree tree      = await client.PostTreeAsync(project, masterSha, gitObjects);

                            string    commitMessage = "Update Docker image digests";
                            GitCommit commit        = await client.PostCommitAsync(
                                project, commitMessage, tree.Sha, new[] { masterSha });

                            // Only fast-forward. Don't overwrite other changes: throw exception instead.
                            await client.PatchReferenceAsync(project, masterRef, commit.Sha, force : false);
                        }

                        break;
                    }
                    catch (HttpRequestException ex) when(i < (MaxTries - 1))
                    {
                        Logger.WriteMessage($"Encountered exception committing build-info update: {ex.Message}");
                        Logger.WriteMessage($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - i - 1} tries left.");
                        await Task.Delay(RetryMillisecondsDelay);
                    }
                }
            }
        }
Esempio n. 5
0
        async Task <SaveResult> CreateOrUpdateGithubPost(string postTitle, string content, IEnumerable <FileReference> referencedFiles, BlogSetting blog)
        {
            var treeToUpload   = new GitTree();
            var imagesToUpload = referencedFiles.Where(f => !f.Saved).ToList();

            if (imagesToUpload.Count > 0)
            {
                foreach (var imageToUpload in imagesToUpload)
                {
                    var imageContent = Convert.ToBase64String(File.ReadAllBytes(imageToUpload.FullPath));
                    var item         = new GitFile
                    {
                        type    = "tree",
                        path    = imageToUpload.FullPath,
                        mode    = ((int)GitTreeMode.SubDirectory),
                        content = imageContent
                    };

                    treeToUpload.tree.Add(item);
                }
            }

            var gitFile = new GitFile
            {
                path    = postTitle,
                content = content,
                mode    = (int)GitTreeMode.File,
                type    = "blob"
            };

            treeToUpload.tree.Add(gitFile);

            var newTree = await githubApi.NewTree(blog.Token, blog.Username, blog.WebAPI, blog.BlogInfo.blogid, treeToUpload);

            var uploadedFile = newTree.Item1.tree.Single(t => t.path == gitFile.path);

            foreach (var fileReference in imagesToUpload)
            {
                fileReference.Saved = true;
            }

            return(new SaveResult
            {
                Id = uploadedFile.sha,
                NewDocumentContent = content
            });
        }
        private async Task <bool> PushUploadsAsync(
            BuildManifestLocation location,
            string message,
            string remoteCommit,
            IEnumerable <SupplementaryUploadRequest> uploads)
        {
            GitObject[] objects = uploads
                                  .Select(upload => new GitObject
            {
                Path = upload.GetAbsolutePath(location.GitHubBasePath),
                Mode = GitObject.ModeFile,
                Type = GitObject.TypeBlob,
                // Always upload files using LF to avoid bad dev scenarios with Git autocrlf.
                Content = upload.Contents.Replace("\r\n", "\n")
            })
                                  .ToArray();

            GitTree tree = await _github.PostTreeAsync(
                location.GitHubProject,
                remoteCommit,
                objects);

            GitCommit commit = await _github.PostCommitAsync(
                location.GitHubProject,
                message,
                tree.Sha,
                new[] { remoteCommit });

            try
            {
                // Only fast-forward. Don't overwrite other changes: throw exception instead.
                await _github.PatchReferenceAsync(
                    location.GitHubProject,
                    location.GitHubRef,
                    commit.Sha,
                    force : false);
            }
            catch (NotFastForwardUpdateException e)
            {
                // Retry if there has been a commit since this update attempt started.
                Trace.TraceInformation($"Retrying: {e.Message}");
                return(false);
            }

            return(true);
        }
Esempio n. 7
0
        public byte[] RawData()
        {
            using (var stream = new MemoryStream())
            {
                stream.Write($"commit {DataSize}\x00");
                stream.Write($"tree {GitTree.ToSha().ToHex()}\n");

                foreach (var parent in Parents)
                {
                    stream.Write($"parent {parent.ToSha().ToHex()}\n");
                }

                stream.Write($"author {Author}\n");
                stream.Write($"committer {Committer}\n");

                if (!string.IsNullOrEmpty(Encoding))
                {
                    stream.Write($"encoding {Encoding}\n");
                }

                foreach (var mergeTag in MergeTag)
                {
                    stream.Write($"mergetag object {mergeTag.Object.ToSha().ToHex()}\n");
                    stream.Write($" type {mergeTag.Type}\n");
                    stream.Write($" tag {mergeTag.Tag}\n");
                    stream.Write($" tagger {mergeTag.Tagger}\n");
                    stream.Write(mergeTag.Text);
                }

                if (Signature != null)
                {
                    stream.Write($"gpgsig -----BEGIN PGP SIGNATURE-----\n{Signature.Text} -----END PGP SIGNATURE-----\n");
                }

                foreach (var line in Other)
                {
                    stream.Write($"{line}\n");
                }

                stream.Write($"\n{Message}");

                return(stream.ToArray());
            }
        }
Esempio n. 8
0
        public static async Task <GitReference> PushChangesAsync(IGitHubClient client, IGitOptionsHost options, string commitMessage, Func <GitHubBranch, Task <IEnumerable <GitObject> > > getChanges)
        {
            GitOptions    gitOptions = options.GitOptions;
            GitHubProject project    = new GitHubProject(gitOptions.Repo, gitOptions.Owner);
            GitHubBranch  branch     = new GitHubBranch(gitOptions.Branch, project);

            IEnumerable <GitObject> changes = await getChanges(branch);

            if (!changes.Any())
            {
                return(null);
            }

            string       masterRef     = $"heads/{gitOptions.Branch}";
            GitReference currentMaster = await client.GetReferenceAsync(project, masterRef);

            string masterSha = currentMaster.Object.Sha;

            if (!options.IsDryRun)
            {
                GitTree tree = await client.PostTreeAsync(project, masterSha, changes.ToArray());

                GitCommit commit = await client.PostCommitAsync(
                    project, commitMessage, tree.Sha, new[] { masterSha });

                // Only fast-forward. Don't overwrite other changes: throw exception instead.
                return(await client.PatchReferenceAsync(project, masterRef, commit.Sha, force : false));
            }
            else
            {
                Logger.WriteMessage($"The following files would have been updated at {gitOptions.Owner}/{gitOptions.Repo}/{gitOptions.Branch}:");
                Logger.WriteMessage();
                foreach (GitObject gitObject in changes)
                {
                    Logger.WriteMessage($"{gitObject.Path}:");
                    Logger.WriteMessage(gitObject.Content);
                    Logger.WriteMessage();
                }

                return(null);
            }
        }
        private async Task <bool> PushUploadsAsync(
            GitHubProject project,
            string @ref,
            string basePath,
            string message,
            string remoteCommit,
            IEnumerable <SupplementaryUploadRequest> uploads)
        {
            GitObject[] objects = uploads
                                  .Select(upload => new GitObject
            {
                Path    = $"{basePath}/{upload.Path}",
                Mode    = GitObject.ModeFile,
                Type    = GitObject.TypeBlob,
                Content = upload.Contents
            })
                                  .ToArray();

            GitTree tree = await _github.PostTreeAsync(project, remoteCommit, objects);

            GitCommit commit = await _github.PostCommitAsync(
                project,
                message,
                tree.Sha,
                new[] { remoteCommit });

            try
            {
                // Only fast-forward. Don't overwrite other changes: throw exception instead.
                await _github.PatchReferenceAsync(project, @ref, commit.Sha, force : false);
            }
            catch (NotFastForwardUpdateException e)
            {
                // Retry if there has been a commit since this update attempt started.
                Trace.TraceInformation($"Retrying: {e.Message}");
                return(false);
            }

            return(true);
        }
Esempio n. 10
0
        async Task <string> CreateOrUpdateGithubPost(string postTitle, string content,
                                                     ICollection <string> imagesToUpload, BlogSetting blog)
        {
            var treeToUpload = new GitTree();

            if (imagesToUpload.Count > 0)
            {
                foreach (var imageToUpload in imagesToUpload)
                {
                    var imageContent = Convert.ToBase64String(File.ReadAllBytes(imageToUpload));
                    var item         = new GitFile
                    {
                        type    = "tree",
                        path    = imageToUpload,
                        mode    = ((int)GitTreeMode.SubDirectory),
                        content = imageContent
                    };
                    treeToUpload.tree.Add(item);
                }
            }

            var gitFile = new GitFile
            {
                path    = postTitle,
                content = content,
                mode    = (int)GitTreeMode.File,
                type    = "blob"
            };

            treeToUpload.tree.Add(gitFile);

            var newTree = await githubApi.NewTree(blog.Token, blog.Username, blog.WebAPI, blog.BlogInfo.blogid, treeToUpload);

            var uploadedFile = newTree.Item1.tree.Single(t => t.path == gitFile.path);

            return(uploadedFile.sha);
        }
        /// <param name="updateLatestVersion">If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty.</param>
        /// <param name="updateLatestPackageList">If true, updates Latest_Packages.txt.</param>
        /// <param name="updateLastBuildPackageList">If true, updates Last_Build_Packages.txt, and enables keeping old packages in Latest_Packages.txt.</param>
        public async Task UpdateBuildInfoAsync(
            IEnumerable <string> packagePaths,
            string versionsRepoPath,
            bool updateLatestPackageList    = true,
            bool updateLatestVersion        = true,
            bool updateLastBuildPackageList = true)
        {
            if (packagePaths == null)
            {
                throw new ArgumentNullException(nameof(packagePaths));
            }
            if (versionsRepoPath == null)
            {
                throw new ArgumentNullException(nameof(versionsRepoPath));
            }

            NupkgInfo[] packages = CreatePackageInfos(packagePaths).ToArray();

            string prereleaseVersion = GetPrereleaseVersion(packages);

            Dictionary <string, string> packageDictionary = CreatePackageInfoDictionary(packages);

            using (GitHubClient client = new GitHubClient(_gitHubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        // Master commit to use as new commit's parent.
                        string       masterRef     = "heads/master";
                        GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef);

                        string masterSha = currentMaster.Object.Sha;

                        List <GitObject> objects = new List <GitObject>();

                        if (updateLastBuildPackageList)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LastBuildPackagesTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(packageDictionary)
                            });
                        }

                        if (updateLatestPackageList)
                        {
                            var allPackages = new Dictionary <string, string>(packageDictionary);

                            if (updateLastBuildPackageList)
                            {
                                await AddExistingPackages(
                                    client,
                                    new GitHubBranch("master", _project),
                                    versionsRepoPath,
                                    allPackages);
                            }

                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LatestPackagesTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(allPackages)
                            });
                        }

                        if (updateLatestVersion)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LatestTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = prereleaseVersion
                            });
                        }

                        string message = $"Updating {versionsRepoPath}";
                        if (string.IsNullOrEmpty(prereleaseVersion))
                        {
                            message += ". No prerelease versions published.";
                        }
                        else
                        {
                            message += $" for {prereleaseVersion}";
                        }

                        GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray());

                        GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha });

                        // Only fast-forward. Don't overwrite other changes: throw exception instead.
                        await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force : false);

                        Trace.TraceInformation($"Committed build-info update on attempt {i + 1}.");
                        break;
                    }
                    catch (Exception ex) when(ex is HttpRequestException || ex is NotFastForwardUpdateException)
                    {
                        int nextTry = i + 1;

                        if (nextTry < MaxTries)
                        {
                            Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}");
                            Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left.");
                            await Task.Delay(RetryMillisecondsDelay);
                        }
                        else
                        {
                            Trace.TraceInformation("Encountered exception committing build-info update.");
                            throw;
                        }
                    }
                }
            }
        }
Esempio n. 12
0
        /// <param name="updateLatestVersion">If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty.</param>
        /// <param name="updateLatestPackageList">If true, updates Latest_Packages.txt.</param>
        /// <param name="updateLastBuildPackageList">If true, updates Last_Build_Packages.txt, and enables keeping old packages in Latest_Packages.txt.</param>
        public async Task UpdateBuildInfoAsync(
            IEnumerable <string> packagePaths,
            string versionsRepoPath,
            bool updateLatestPackageList    = true,
            bool updateLatestVersion        = true,
            bool updateLastBuildPackageList = true)
        {
            if (packagePaths == null)
            {
                throw new ArgumentNullException(nameof(packagePaths));
            }
            if (versionsRepoPath == null)
            {
                throw new ArgumentNullException(nameof(versionsRepoPath));
            }

            NupkgInfo[] packages = CreatePackageInfos(packagePaths).ToArray();

            string prereleaseVersion = packages
                                       .Select(t => t.Prerelease)
                                       .FirstOrDefault(prerelease => !string.IsNullOrEmpty(prerelease))
                                       ?? "stable";

            Dictionary <string, string> packageDictionary = CreatePackageInfoDictionary(packages);

            using (GitHubClient client = new GitHubClient(_gitHubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        // Master commit to use as new commit's parent.
                        string       masterRef     = "heads/master";
                        GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef);

                        string masterSha = currentMaster.Object.Sha;

                        List <GitObject> objects = new List <GitObject>();

                        if (updateLastBuildPackageList)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Last_Build_Packages.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(packageDictionary)
                            });
                        }

                        if (updateLatestPackageList)
                        {
                            string latestPackagesPath = $"{versionsRepoPath}/Latest_Packages.txt";

                            var allPackages = new Dictionary <string, string>(packageDictionary);

                            if (updateLastBuildPackageList)
                            {
                                Dictionary <string, string> existingPackages = await GetPackagesAsync(client, latestPackagesPath);

                                if (existingPackages == null)
                                {
                                    Trace.TraceInformation(
                                        "No exising Latest_Packages file found; one will be " +
                                        $"created in '{versionsRepoPath}'");
                                }
                                else
                                {
                                    // Add each existing package if there isn't a new package with the same id.
                                    foreach (var package in existingPackages)
                                    {
                                        if (!allPackages.ContainsKey(package.Key))
                                        {
                                            allPackages[package.Key] = package.Value;
                                        }
                                    }
                                }
                            }

                            objects.Add(new GitObject
                            {
                                Path    = latestPackagesPath,
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(allPackages)
                            });
                        }

                        if (updateLatestVersion)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Latest.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = prereleaseVersion
                            });
                        }

                        string message = $"Updating {versionsRepoPath}";
                        if (string.IsNullOrEmpty(prereleaseVersion))
                        {
                            message += ". No prerelease versions published.";
                        }
                        else
                        {
                            message += $" for {prereleaseVersion}";
                        }

                        GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray());

                        GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha });

                        // Only fast-forward. Don't overwrite other changes: throw exception instead.
                        await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force : false);

                        Trace.TraceInformation($"Committed build-info update on attempt {i + 1}.");
                        break;
                    }
                    catch (HttpRequestException ex)
                    {
                        int nextTry = i + 1;
                        if (nextTry < MaxTries)
                        {
                            Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}");
                            Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left.");
                            await Task.Delay(RetryMillisecondsDelay);
                        }
                        else
                        {
                            Trace.TraceInformation("Encountered exception committing build-info update.");
                            throw;
                        }
                    }
                }
            }
        }
Esempio n. 13
0
        public RepositoryDataModel()
        {
            var user = new User
            {
                Login     = "******",
                AvatarUrl = "https://secure.gravatar.com/avatar/5c4663b12b9e6d8dc6dcdfbfb3dc1317",
            };

            Repository = new Repository
            {
                Owner       = user,
                Name        = "symfony",
                HtmlUrl     = "http://github.com/michelsalib/symfony",
                Description = "The Symfony2 PHP framework",
                Watchers    = 3,
                Forks       = 1,
                Homepage    = "symfony.com",
                Parent      = new Repository
                {
                    Owner = user,
                    Name  = "symfnoy"
                }
            };

            Tree = new GitTree
            {
                Tree = new List <GitHubFile>
                {
                    new GitHubFile
                    {
                        Path = "readme.md",
                        Type = "blob",
                    },
                    new GitHubFile
                    {
                        Path = "dir",
                        Type = "tree",
                    },
                }
            };

            Commits = new ObservableCollection <Push>
            {
                new Push
                {
                    Author = user,
                    Commit = new Commit
                    {
                        Message = "Removing static access to Username on github service",
                        Author  = new Committer
                        {
                            Date = DateTime.Now,
                        }
                    }
                }
            };

            PullRequests = new ObservableCollection <PullRequest>
            {
                new PullRequest
                {
                    Title     = "my pull requets",
                    Body      = "the description",
                    UpdatedAt = DateTime.Now,
                    State     = "Open",
                    User      = user,
                }
            };

            Issues = new ObservableCollection <Issue>
            {
                new Issue
                {
                    Title     = "my issue",
                    Body      = "the description is very long the description is very long the description is very long the description is very long the description is very long the description is very long the description is very long",
                    UpdatedAt = DateTime.Now,
                    State     = "Open",
                    User      = user,
                }
            };
        }
        private static bool IsRelevantCommit(GitRepository repository, GitTree tree, GitTree?parent, string relativePath, IReadOnlyList <FilterPath> filters)
        {
            // Walk over all child nodes in the current tree. If a child node was found in the parent,
            // remove it, so that after the iteration the parent contains all nodes which have been
            // deleted.
            foreach (var child in tree.Children)
            {
                var          entry       = child.Value;
                GitTreeEntry?parentEntry = null;

                // If the entry is not present in the parent commit, it was added;
                // if the Sha does not match, it was modified.
                if (parent is null ||
                    !parent.Children.TryGetValue(child.Key, out parentEntry) ||
                    parentEntry.Sha != child.Value.Sha)
                {
                    // Determine whether the change was relevant.
                    var fullPath = $"{relativePath}{entry.Name}";

                    bool isRelevant =
                        // Either there are no include filters at all (i.e. everything is included), or there's an explicit include filter
                        (!filters.Any(f => f.IsInclude) || filters.Any(f => f.Includes(fullPath, repository.IgnoreCase)) ||
                         (!entry.IsFile && filters.Any(f => f.IncludesChildren(fullPath, repository.IgnoreCase))))
                        // The path is not excluded by any filters
                        && !filters.Any(f => f.Excludes(fullPath, repository.IgnoreCase));

                    // If the change was relevant, and the item is a directory, we need to recurse.
                    if (isRelevant && !entry.IsFile)
                    {
                        isRelevant = IsRelevantCommit(
                            repository,
                            repository.GetTree(entry.Sha),
                            parentEntry is null ? GitTree.Empty : repository.GetTree(parentEntry.Sha),
                            $"{fullPath}/",
                            filters);
                    }

                    // Quit as soon as any relevant change has been detected.
                    if (isRelevant)
                    {
                        return(true);
                    }
                }

                if (parentEntry is not null)
                {
                    Assumes.NotNull(parent);
                    parent.Children.Remove(child.Key);
                }
            }

            // Inspect removed entries (i.e. present in parent but not in the current tree)
            if (parent is not null)
            {
                foreach (var child in parent.Children)
                {
                    // Determine whether the change was relevant.
                    var fullPath = Path.Combine(relativePath, child.Key);

                    bool isRelevant =
                        filters.Any(f => f.Includes(fullPath, repository.IgnoreCase)) &&
                        !filters.Any(f => f.Excludes(fullPath, repository.IgnoreCase));

                    if (isRelevant)
                    {
                        return(true);
                    }
                }
            }

            // No relevant changes have been detected
            return(false);
        }
Esempio n. 15
0
        /// <param name="updateLatestVersion">If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty.</param>
        /// <param name="updateLatestPackageList">If true, updates Latest_Packages.txt.</param>
        public async Task UpdateBuildInfoAsync(
            string versionIdentifier,
            string version,
            string versionsRepoPath,
            bool updateLatestPackageList = true,
            bool updateLatestVersion     = true)
        {
            if (versionIdentifier == null)
            {
                throw new ArgumentNullException(nameof(versionIdentifier));
            }
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (versionsRepoPath == null)
            {
                throw new ArgumentNullException(nameof(versionsRepoPath));
            }

            using (GitHubClient client = new GitHubClient(_gitHubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        // Master commit to use as new commit's parent.
                        string       masterRef     = "heads/master";
                        GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef);

                        string masterSha = currentMaster.Object.Sha;

                        List <GitObject> objects = new List <GitObject>();

                        if (updateLatestVersion)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Latest.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = version
                            });
                        }
                        if (updateLatestPackageList)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Latest_Packages.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = $"{versionIdentifier} {version}{Environment.NewLine}"
                            });
                        }
                        string message = $"Updating {versionsRepoPath}";

                        GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray());

                        GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha });

                        // Only fast-forward. Don't overwrite other changes: throw exception instead.
                        await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force : false);

                        Trace.TraceInformation($"Committed build-info update on attempt {i + 1}.");
                        break;
                    }
                    catch (HttpRequestException ex)
                    {
                        int nextTry = i + 1;
                        if (nextTry < MaxTries)
                        {
                            Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}");
                            Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left.");
                            await Task.Delay(RetryMillisecondsDelay);
                        }
                        else
                        {
                            Trace.TraceInformation("Encountered exception committing build-info update.");
                            throw;
                        }
                    }
                }
            }
        }
Esempio n. 16
0
        public bool TryGet(string path, [NotNullWhen(true)] out GitTreeItem?item)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            GitTree tree = _gitTree;

            int n = -1;

            do
            {
                int start = n + 1;
                n = path.IndexOf('/', start);
                if (n < 0)
                {
                    n = path.Length;
                }
                else if (n == start)
                {
                    item = null;
                    return(false);
                }

                string sp    = path.Substring(start, n - start);
                bool   found = false;
                foreach (var i in tree)
                {
                    if (i.Name == sp)
                    {
                        if (n == path.Length && (!_justFiles || i.ElementType.IsFile()))
                        {
                            item = new GitTreeItem(path, i);
                            return(true);
                        }

                        if (i.ElementType == GitTreeElementType.Directory)
                        {
                            tree = (GitTree)i.GitObject;
                        }
                        else if (i.ElementType == GitTreeElementType.GitCommitLink)
                        {
                            tree = ((GitCommit)i.GitObject).Tree;
                        }
                        else
                        {
                            item = null;
                            return(false);
                        }
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    break;
                }
            }while (n < path.Length);

            item = null;
            return(false);
        }