public void GivenARemoteGitRepositoryWithCommitsAndBranches_ThenClonedLocalShouldMatchRemoteVersion()
    {
        using (var fixture = new RemoteRepositoryFixture(
            path =>
            {
                Repository.Init(path);
                Console.WriteLine("Created git repository at '{0}'", path);

                var repo = new Repository(path);
                repo.MakeCommits(5);

                repo.CreateBranch("develop");
                repo.CreateBranch("release-1.0");

                repo.Checkout("release-1.0");
                repo.MakeCommits(5);

                return repo;
            }))
        {
            GitRepositoryHelper.NormalizeGitDirectory(fixture.LocalRepositoryFixture.RepositoryPath, new AuthenticationInfo(), noFetch: false, currentBranch: string.Empty);

            fixture.AssertFullSemver("1.0.0-beta.1+5");
            fixture.AssertFullSemver("1.0.0-beta.1+5", fixture.LocalRepositoryFixture.Repository);
        }
    }
    public void GivenARemoteGitRepositoryWithCommitsAndBranches_ThenClonedLocalShouldMatchRemoteVersion()
    {
        using (var fixture = new RemoteRepositoryFixture(
            path =>
            {
                Repository.Init(path);
                Console.WriteLine("Created git repository at '{0}'", path);

                var repo = new Repository(path);
                repo.MakeCommits(5);

                repo.CreateBranch("develop");
                repo.CreateBranch("release-1.0");

                repo.Checkout("release-1.0");
                repo.MakeCommits(5);

                return repo;
            },
            new Config()))
        {
            fixture.AssertFullSemver("1.0.0-beta.1+5");
            fixture.AssertFullSemver("1.0.0-beta.1+5", fixture.LocalRepository);
        }
    }
Example #3
0
        public void CanFastForwardRepos(bool shouldMergeOccurInDetachedHeadState)
        {
            const string firstBranchFileName = "first branch file.txt";
            const string sharedBranchFileName = "first+second branch file.txt";

            string path = CloneStandardTestRepo();
            using (var repo = new Repository(path))
            {
                // Reset the index and the working tree.
                repo.Reset(ResetMode.Hard);

                // Clean the working directory.
                repo.RemoveUntrackedFiles();

                var firstBranch = repo.CreateBranch("FirstBranch");
                firstBranch.Checkout();

                // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit).
                AddFileCommitToRepo(repo, sharedBranchFileName);

                var secondBranch = repo.CreateBranch("SecondBranch");

                // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one).
                AddFileCommitToRepo(repo, firstBranchFileName);

                if (shouldMergeOccurInDetachedHeadState)
                {
                    // Detaches HEAD
                    repo.Checkout(secondBranch.Tip);
                }
                else
                {
                    secondBranch.Checkout();
                }

                Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached);

                MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature);

                Assert.Equal(MergeStatus.FastForward, mergeResult.Status);
                Assert.Equal(repo.Branches["FirstBranch"].Tip, mergeResult.Commit);
                Assert.Equal(repo.Branches["FirstBranch"].Tip, repo.Head.Tip);
                Assert.Equal(repo.Head.Tip, mergeResult.Commit);

                Assert.Equal(0, repo.Index.RetrieveStatus().Count());
                Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached);

                if (!shouldMergeOccurInDetachedHeadState)
                {
                    // Ensure HEAD is still attached and points to SecondBranch
                    Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName);
                }
            }
        }
Example #4
0
        public void CanFollowFirstParent()
        {
            string path = SandboxStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var branch = repo.CreateBranch("branch");

                // Make an earlier tag on master
                repo.Commit("A", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true });
                repo.ApplyTag("firstParentTag");

                // Make a later tag on branch
                Commands.Checkout(repo, branch);
                repo.Commit("B", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true });
                repo.ApplyTag("mostRecentTag");

                Commands.Checkout(repo, "master");
                repo.Commit("C", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true });
                repo.Merge(branch, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastForward });

                // With OnlyFollowFirstParent = false, the most recent tag reachable should be returned
                Assert.Equal("mostRecentTag-3-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = false, Strategy = DescribeStrategy.Tags }));

                // With OnlyFollowFirstParent = true, the most recent tag on the current branch should be returned
                Assert.Equal("firstParentTag-2-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = true, Strategy = DescribeStrategy.Tags }));

            }
        }
Example #5
0
    static void CreateFakePullRequest(string repoPath, string issueNumber)
    {
        // Fake an upstream repository as it would appear on GitHub
        // will pull requests stored under the refs/pull/ namespace
        using (var repo = new Repository(repoPath))
        {
            var branch = repo.CreateBranch("temp", repo.Branches["develop"].Tip);
            branch.Checkout();

            AddOneCommitToHead(repo, "code");
            AddOneCommitToHead(repo, "code");

            var c = repo.Head.Tip;
            repo.Refs.Add(string.Format("refs/pull/{0}/head", issueNumber), c.Id);

            var sign = SignatureBuilder.SignatureNow();
            var m = repo.ObjectDatabase.CreateCommit(
                sign, sign,
                string.Format("Merge pull request #{0} from nulltoken/ntk/fix/{0}", issueNumber)
                , c.Tree, new[] { repo.Branches["develop"].Tip, c }, true);

            repo.Refs.Add(string.Format("refs/pull/{0}/merge", issueNumber), m.Id);

            repo.Checkout("develop");
            repo.Branches.Remove("temp");
        }
    }
Example #6
0
        public void CanCancelCheckoutThroughNotifyCallback()
        {
            string repoPath = InitNewRepository();

            using (var repo = new Repository(repoPath))
            {
                string relativePath = "a.txt";
                Touch(repo.Info.WorkingDirectory, relativePath, "Hello\n");

                repo.Index.Stage(relativePath);
                repo.Commit("Initial commit", Constants.Signature, Constants.Signature);

                // Create 2nd branch
                repo.CreateBranch("branch2");

                // Update file in main
                Touch(repo.Info.WorkingDirectory, relativePath, "Hello from master!\n");
                repo.Index.Stage(relativePath);
                repo.Commit("2nd commit", Constants.Signature, Constants.Signature);

                // Checkout branch2
                repo.Checkout("branch2");

                // Update the context of a.txt - a.txt will then conflict between branch2 and master.
                Touch(repo.Info.WorkingDirectory, relativePath, "Hello From branch2!\n");

                // Verify that we get called for the notify conflict cb
                string conflictPath = string.Empty;
                CheckoutNotificationOptions checkoutNotifications = new CheckoutNotificationOptions((path, flags) => { conflictPath = path; return false; }, CheckoutNotifyFlags.Conflict);
                Assert.Throws<UserCancelledException>(() => repo.Checkout("master", CheckoutModifiers.None, null, checkoutNotifications));
                Assert.Equal(relativePath, conflictPath);
            }
        }
Example #7
0
        public void CanCommitALittleBit()
        {
            SelfCleaningDirectory scd = BuildSelfCleaningDirectory();
            string dir = Repository.Init(scd.DirectoryPath);
            Path.IsPathRooted(dir).ShouldBeTrue();
            Directory.Exists(dir).ShouldBeTrue();

            using (var repo = new Repository(dir))
            {
                const string relativeFilepath = "new.txt";
                string filePath = Path.Combine(repo.Info.WorkingDirectory, relativeFilepath);

                File.WriteAllText(filePath, "null");
                repo.Index.Stage(relativeFilepath);
                File.AppendAllText(filePath, "token\n");
                repo.Index.Stage(relativeFilepath);

                repo.Head[relativeFilepath].ShouldBeNull();

                var author = new Signature("Author N. Ame", "*****@*****.**", DateTimeOffset.Now.AddSeconds(-10));
                Commit commit = repo.Commit("Initial egotistic commit", author, author);

                AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n");
                AssertBlobContent(commit[relativeFilepath], "nulltoken\n");

                commit.Parents.Count().ShouldEqual(0);
                repo.Info.IsEmpty.ShouldBeFalse();

                File.WriteAllText(filePath, "nulltoken commits!\n");
                repo.Index.Stage(relativeFilepath);

                var author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5));
                Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2);

                AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n");
                AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n");

                commit2.Parents.Count().ShouldEqual(1);
                commit2.Parents.First().Id.ShouldEqual(commit.Id);

                Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit.Id.Sha); //TODO: This cries for a shortcut method :-/
                repo.Branches.Checkout(firstCommitBranch.Name); //TODO: This cries for a shortcut method :-/

                File.WriteAllText(filePath, "davidfowl commits!\n");

                var author3 = new Signature("David Fowler", "*****@*****.**", author.When.AddSeconds(2));
                repo.Index.Stage(relativeFilepath);

                Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3);

                AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n");
                AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n");

                commit3.Parents.Count().ShouldEqual(1);
                commit3.Parents.First().Id.ShouldEqual(commit.Id);

                AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n");
            }
        }
Example #8
0
 public void CanCreateBranchFromExplicitHead()
 {
     TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
     using (var repo = new Repository(path.RepositoryPath))
     {
         const string name = "unit_test";
         Branch newBranch = repo.CreateBranch(name, "HEAD");
         newBranch.ShouldNotBeNull();
         newBranch.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
     }
 }
        public void CherryPickWithConflictDoesNotCommit()
        {
            const string firstBranchFileName = "first branch file.txt";
            const string secondBranchFileName = "second branch file.txt";
            const string sharedBranchFileName = "first+second branch file.txt";

            string path = SandboxStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var firstBranch = repo.CreateBranch("FirstBranch");
                repo.Checkout(firstBranch);

                // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit).
                AddFileCommitToRepo(repo, sharedBranchFileName);

                var secondBranch = repo.CreateBranch("SecondBranch");
                // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one).
                AddFileCommitToRepo(repo, firstBranchFileName);
                AddFileCommitToRepo(repo, sharedBranchFileName, "The first branches comment");  // Change file in first branch

                repo.Checkout(secondBranch);
                // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit).
                AddFileCommitToRepo(repo, secondBranchFileName);
                AddFileCommitToRepo(repo, sharedBranchFileName, "The second branches comment");  // Change file in second branch

                CherryPickResult cherryPickResult = repo.CherryPick(repo.Branches["FirstBranch"].Tip, Constants.Signature);

                Assert.Equal(CherryPickStatus.Conflicts, cherryPickResult.Status);

                Assert.Null(cherryPickResult.Commit);
                Assert.Equal(1, repo.Index.Conflicts.Count());

                var conflict = repo.Index.Conflicts.First();
                var changes = repo.Diff.Compare(repo.Lookup<Blob>(conflict.Theirs.Id), repo.Lookup<Blob>(conflict.Ours.Id));

                Assert.False(changes.IsBinaryComparison);
            }
        }
Example #10
0
 public void CanCreateBranchFromImplicitHead()
 {
     TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
     using (var repo = new Repository(path.RepositoryPath))
     {
         const string name = "unit_test";
         Branch newBranch = repo.CreateBranch(name);
         newBranch.ShouldNotBeNull();
         newBranch.Name.ShouldEqual(name);
         newBranch.CanonicalName.ShouldEqual("refs/heads/" + name);
         newBranch.IsCurrentRepositoryHead.ShouldBeFalse();
         newBranch.Tip.ShouldNotBeNull();
         newBranch.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
         repo.Branches.SingleOrDefault(p => p.Name == name).ShouldNotBeNull();
     }
 }
Example #11
0
        public void CanCreateBranch()
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
            using (var repo = new Repository(path.RepositoryPath))
            {
                const string name = "unit_test";
                Branch newBranch = repo.CreateBranch(name, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
                newBranch.ShouldNotBeNull();
                newBranch.Name.ShouldEqual(name);
                newBranch.CanonicalName.ShouldEqual("refs/heads/" + name);
                newBranch.Tip.ShouldNotBeNull();
                newBranch.Tip.Sha.ShouldEqual("be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
                repo.Branches.SingleOrDefault(p => p.Name == name).ShouldNotBeNull();

                repo.Branches.Delete(newBranch.Name);
            }
        }
Example #12
0
        public void AppendingToReflogDependsOnCoreLogAllRefUpdatesSetting(bool isBare, bool? setting, bool expectAppend)
        {
            var repoPath = InitNewRepository(isBare);

            using (var repo = new Repository(repoPath))
            {
                if (setting != null)
                {
                    EnableRefLog(repo, setting.Value);
                }

                var blob = repo.ObjectDatabase.CreateBlob(Stream.Null);
                var tree = repo.ObjectDatabase.CreateTree(new TreeDefinition().Add("yoink", blob, Mode.NonExecutableFile));
                var commit = repo.ObjectDatabase.CreateCommit(Constants.Signature, Constants.Signature, "yoink",
                                                 tree, Enumerable.Empty<Commit>(), false);

                var branch = repo.CreateBranch("yoink", commit);
                var log = repo.Refs.Log(branch.CanonicalName);

                Assert.Equal(expectAppend ? 1 : 0, log.Count());
            }
        }
        public void CorrectlyEncodesAndDecodesInput()
        {
            const string decodedInput = "This is a substitution cipher";
            const string encodedInput = "Guvf vf n fhofgvghgvba pvcure";

            var attributes = new List<FilterAttributeEntry> { new FilterAttributeEntry("rot13") };
            var filter = new SubstitutionCipherFilter("cipher-filter", attributes);
            var filterRegistration = GlobalSettings.RegisterFilter(filter);

            string repoPath = InitNewRepository();
            string fileName = Guid.NewGuid() + ".rot13";
            using (var repo = new Repository(repoPath))
            {
                CreateConfigurationWithDummyUser(repo, Constants.Identity);
                CreateAttributesFile(repo, "*.rot13 filter=rot13");

                var blob = CommitOnBranchAndReturnDatabaseBlob(repo, fileName, decodedInput);
                var textDetected = blob.GetContentText();

                Assert.Equal(encodedInput, textDetected);
                Assert.Equal(1, filter.CleanCalledCount);
                Assert.Equal(0, filter.SmudgeCalledCount);

                var branch = repo.CreateBranch("delete-files");
                Commands.Checkout(repo, branch.FriendlyName);

                DeleteFile(repo, fileName);

                Commands.Checkout(repo, "master");

                var fileContents = ReadTextFromFile(repo, fileName);
                Assert.Equal(1, filter.SmudgeCalledCount);
                Assert.Equal(decodedInput, fileContents);
            }

            GlobalSettings.DeregisterFilter(filterRegistration);
        }
    public void GivenARemoteWithATagOnMaster_AndAPullRequestWithTwoCommits_AndBuildIsRunningInTeamCity_VersionIsCalculatedProperly(string pullRequestRef)
    {
        using (var fixture = new EmptyRepositoryFixture())
        {
            var remoteRepositoryPath = PathHelper.GetTempPath();
            Repository.Init(remoteRepositoryPath);
            using (var remoteRepository = new Repository(remoteRepositoryPath))
            {
                remoteRepository.Config.Set("user.name", "Test");
                remoteRepository.Config.Set("user.email", "*****@*****.**");
                fixture.Repository.Network.Remotes.Add("origin", remoteRepositoryPath);
                Console.WriteLine("Created git repository at {0}", remoteRepositoryPath);
                remoteRepository.MakeATaggedCommit("1.0.3");

                var branch = remoteRepository.CreateBranch("FeatureBranch");
                remoteRepository.Checkout(branch);
                remoteRepository.MakeCommits(2);
                remoteRepository.Checkout(remoteRepository.Head.Tip.Sha);
                //Emulate merge commit
                var mergeCommitSha = remoteRepository.MakeACommit().Sha;
                remoteRepository.Checkout("master"); // HEAD cannot be pointing at the merge commit
                remoteRepository.Refs.Add(pullRequestRef, new ObjectId(mergeCommitSha));

                // Checkout PR commit
                Commands.Fetch((Repository)fixture.Repository, "origin", new string[0], new FetchOptions(), null);
                fixture.Repository.Checkout(mergeCommitSha);
            }

            var result = GitVersionHelper.ExecuteIn(fixture.RepositoryPath, isTeamCity: true);

            result.ExitCode.ShouldBe(0);
            result.OutputVariables.FullSemVer.ShouldBe("1.0.4-PullRequest0005.3");

            // Cleanup repository files
            DirectoryHelper.DeleteDirectory(remoteRepositoryPath);
        }
    }
Example #15
0
        public void CanFollowBranches(string specificRepoPath)
        {
            var repoPath = specificRepoPath ?? CreateEmptyRepository();
            var path = "Test.txt";

            var dummy = new string('a', 1024);

            using (var repo = new Repository(repoPath))
            {
                var master0 = AddCommitToOdb(repo, "0. Initial commit for this test", path, "Before merge", dummy);
                var fix1 = AddCommitToOdb(repo, "1. Changed on fix", path, "Change on fix branch", dummy, master0);
                var master2 = AddCommitToOdb(repo, "2. Changed on master", path, "Independent change on master branch",
                    dummy, master0);

                path = "New" + path;

                var fix3 = AddCommitToOdb(repo, "3. Changed and renamed on fix", path, "Another change on fix branch",
                    dummy, fix1);
                var master4 = AddCommitToOdb(repo, "4. Changed and renamed on master", path,
                    "Another independent change on master branch", dummy, master2);
                var master5 = AddCommitToOdb(repo, "5. Merged fix into master", path,
                    "Manual resolution of merge conflict", dummy, master4, fix3);
                var master6 = AddCommitToOdb(repo, "6. Changed on master", path, "Change after merge", dummy, master5);
                var nextfix7 = AddCommitToOdb(repo, "7. Changed on next-fix", path, "Change on next-fix branch", dummy,
                    master6);
                var master8 = AddCommitToOdb(repo, "8. Changed on master", path,
                    "Some arbitrary change on master branch", dummy, master6);
                var master9 = AddCommitToOdb(repo, "9. Merged next-fix into master", path,
                    "Another manual resolution of merge conflict", dummy, master8, nextfix7);
                var master10 = AddCommitToOdb(repo, "10. Changed on master", path, "A change on master after merging",
                    dummy, master9);

                repo.CreateBranch("master", master10);
                Commands.Checkout(repo, "master", new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force });

                // Test --date-order.
                var timeHistory = repo.Commits.QueryBy(path,
                    new CommitFilter { SortBy = CommitSortStrategies.Time });
                var timeCommits = new List<Commit>
                {
                    master10, // master

                    master8, // master
                    nextfix7, // next-fix
                    master6, // master

                    master4, // master
                    fix3, // fix
                    master2, // master
                    fix1, // fix
                    master0 // master (initial commit)
                };
                Assert.Equal(timeCommits, timeHistory.Select(e => e.Commit));

                // Test --topo-order.
                var topoHistory = repo.Commits.QueryBy(path,
                    new CommitFilter { SortBy = CommitSortStrategies.Topological });
                var topoCommits = new List<Commit>
                {
                    master10, // master

                    nextfix7, // next-fix
                    master8, // master
                    master6, // master

                    fix3, // fix
                    fix1, // fix
                    master4, // master
                    master2, // master
                    master0 // master (initial commit)
                };
                Assert.Equal(topoCommits, topoHistory.Select(e => e.Commit));
            }
        }
Example #16
0
 public void CreateBranch(string branchName)
 {
     _repo.Checkout(_repo.CreateBranch(branchName));
 }
Example #17
0
        public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory)
        {
            if (isDirectory)
            {
                expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar;
            }

            string repoPath = InitNewRepository();

            using (var repo = new Repository(repoPath))
            {
                PopulateBasicRepository(repo);

                string relativePathUpdated = "updated.txt";
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A");
                repo.Stage(relativePathUpdated);
                repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature);

                // Create conflicting change
                string relativePathConflict = "conflict.txt";
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A");
                repo.Stage(relativePathConflict);
                repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature);

                // Create another branch
                repo.CreateBranch("newbranch");

                // Make an edit to conflict.txt and update.txt
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB");
                repo.Stage(relativePathUpdated);
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB");
                repo.Stage(relativePathConflict);

                repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature);

                // Checkout other branch
                repo.Checkout("newbranch");

                // Make alternate edits to conflict.txt and update.txt
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC");
                repo.Stage(relativePathUpdated);
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC");
                repo.Stage(relativePathConflict);
                repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature);

                // make conflicting change to conflict.txt
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD");
                repo.Stage(relativePathConflict);

                // Create ignored change
                string relativePathIgnore = Path.Combine("bin", "ignored.txt");
                Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file");

                // Create untracked change
                string relativePathUntracked = "untracked.txt";
                Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file");

                bool wasCalled = false;
                string actualNotificationPath = string.Empty;
                CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None;

                CheckoutOptions options = new CheckoutOptions()
                {
                    OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return true; },
                    CheckoutNotifyFlags = notifyFlags,
                };

                Assert.Throws<MergeConflictException>(() => repo.Checkout("master", options));

                Assert.True(wasCalled);
                Assert.Equal(expectedNotificationPath, actualNotificationPath);
                Assert.Equal(notifyFlags, actualNotifyFlags);
            }
        }
Example #18
0
        /// <summary>
        /// Adds the standard .NET targets to the build.
        /// </summary>
        /// <param name="build">The build to which to add targets.</param>
        /// <param name="settings">The build settings.</param>
        public static void AddDotNetTargets(this BuildApp build, DotNetBuildSettings settings = null)
        {
            settings = settings ?? new DotNetBuildSettings();

            var buildOptions        = settings.BuildOptions ?? (settings.BuildOptions = new DotNetBuildOptions());
            var configurationOption = buildOptions.ConfigurationOption ?? (buildOptions.ConfigurationOption =
                                                                               build.AddOption("-c|--configuration <name>", "The configuration to build (default Release)", "Release"));
            var platformOption = buildOptions.PlatformOption ?? (buildOptions.PlatformOption =
                                                                     build.AddOption("-p|--platform <name>", "The solution platform to build"));
            var versionSuffixOption = buildOptions.VersionSuffixOption ?? (buildOptions.VersionSuffixOption =
                                                                               build.AddOption("--version-suffix <suffix>", "Generates a prerelease package"));
            var nugetOutputOption = buildOptions.NuGetOutputOption ?? (buildOptions.NuGetOutputOption =
                                                                           build.AddOption("--nuget-output <path>", "Directory for generated package (default release)", "release"));
            var triggerOption = buildOptions.TriggerOption ?? (buildOptions.TriggerOption =
                                                                   build.AddOption("--trigger <name>", "The git branch or tag that triggered the build"));
            var buildNumberOption = buildOptions.BuildNumberOption ?? (buildOptions.BuildNumberOption =
                                                                           build.AddOption("--build-number <number>", "The automated build number"));

            var solutionName    = settings.SolutionName;
            var nugetSource     = settings.NuGetSource ?? "https://api.nuget.org/v3/index.json";
            var msbuildSettings = settings.MSBuildSettings;

            var dotNetTools           = settings.DotNetTools ?? new DotNetTools(Path.Combine("tools", "bin"));
            var sourceLinkVersion     = settings.SourceLinkToolVersion ?? "3.1.1";
            var xmlDocMarkdownVersion = settings.DocsSettings?.ToolVersion ?? "1.5.1";
            var packageDiffVersion    = settings.PackageDiffToolVersion ?? "0.2.1";

            var  packagePaths         = new List <string>();
            bool hasBadPackageVersion = false;

            build.Target("clean")
            .Describe("Deletes all build output")
            .Does(() =>
            {
                foreach (var directory in FindDirectories("{src,tests}/**/{bin,obj}", "tools/bin", "release"))
                {
                    Directory.Delete(directory, recursive: true);
                }

                var extraProperties = getExtraProperties("clean");
                if (msbuildSettings == null)
                {
                    RunDotNet(new[] { "clean", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
                else
                {
                    runMSBuild(new[] { solutionName, "-t:Clean", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
            });

            build.Target("restore")
            .Describe("Restores NuGet packages")
            .Does(() =>
            {
                var extraProperties = getExtraProperties("restore");
                if (msbuildSettings == null)
                {
                    RunDotNet(new[] { "restore", solutionName, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
                else
                {
                    runMSBuild(new[] { solutionName, "-t:Restore", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
            });

            build.Target("build")
            .DependsOn("restore")
            .Describe("Builds the solution")
            .Does(() =>
            {
                var buildNumberArg = buildNumberOption.Value == null ? null : $"-p:BuildNumber={buildNumberOption.Value}";

                var extraProperties = getExtraProperties("build");
                if (msbuildSettings == null)
                {
                    RunDotNet(new[] { "build", solutionName, "-c", configurationOption.Value, getPlatformArg(), buildNumberArg, "--no-restore", "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
                else
                {
                    runMSBuild(new[] { solutionName, $"-p:Configuration={configurationOption.Value}", getPlatformArg(), buildNumberArg, "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties));
                }
            });

            build.Target("test")
            .DependsOn("build")
            .Describe("Runs the unit tests")
            .Does(() =>
            {
                var extraProperties    = getExtraProperties("test");
                var findTestAssemblies = settings.TestSettings?.FindTestAssemblies;
                if (findTestAssemblies != null)
                {
                    foreach (var testAssembly in findTestAssemblies())
                    {
                        RunDotNet(new AppRunnerSettings {
                            Arguments = new[] { "vstest", Path.GetFileName(testAssembly) }.Concat(extraProperties), WorkingDirectory = Path.GetDirectoryName(testAssembly)
                        });
                    }
                }
                else
                {
                    RunDotNet(new[] { "test", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--no-build", getMaxCpuCountArg() }.Concat(extraProperties));
                }
            });

            build.Target("package")
            .DependsOn("test")
            .Describe("Builds NuGet packages")
            .Does(() =>
            {
                string versionSuffix = versionSuffixOption.Value;
                string trigger       = triggerOption.Value;
                if (versionSuffix == null && trigger != null)
                {
                    var group = s_triggerRegex.Match(trigger).Groups["suffix"];
                    if (group.Success)
                    {
                        versionSuffix = group.ToString();
                    }
                }

                var nugetOutputPath = Path.GetFullPath(nugetOutputOption.Value);
                var tempOutputPath  = Path.Combine(nugetOutputPath, $"temp_{Guid.NewGuid():N}");

                var extraProperties = getExtraProperties("package");
                if (msbuildSettings == null)
                {
                    RunDotNet(new[]
                    {
                        "pack", solutionName,
                        "-c", configurationOption.Value,
                        getPlatformArg(),
                        "--no-build",
                        "--output", tempOutputPath,
                        versionSuffix != null ? "--version-suffix" : null, versionSuffix,
                        getMaxCpuCountArg()
                    }.Concat(extraProperties));
                }
                else
                {
                    runMSBuild(new[]
                    {
                        solutionName, "-t:Pack",
                        $"-p:Configuration={configurationOption.Value}",
                        getPlatformArg(),
                        "-p:NoBuild=true",
                        $"-p:PackageOutputPath={tempOutputPath}",
                        versionSuffix != null ? $"-p:VersionSuffix={versionSuffix}" : null,
                        "-v:normal",
                        getMaxCpuCountArg()
                    }.Concat(extraProperties));
                }

                var tempPackagePaths = FindFilesFrom(tempOutputPath, "*.nupkg");
                foreach (var tempPackagePath in tempPackagePaths)
                {
                    var packagePath = Path.Combine(nugetOutputPath, Path.GetFileName(tempPackagePath));
                    if (File.Exists(packagePath))
                    {
                        File.Delete(packagePath);
                    }
                    File.Move(tempPackagePath, packagePath);
                    packagePaths.Add(packagePath);
                }
                Directory.Delete(tempOutputPath);

                if (packagePaths.Count == 0)
                {
                    throw new ApplicationException("No NuGet packages created.");
                }

                var projectUsesSemVer = settings.ProjectUsesSemVer;
                foreach (var packagePath in packagePaths)
                {
                    var packageInfo = GetPackageInfo(packagePath);
                    if (projectUsesSemVer == null || projectUsesSemVer(packageInfo.Name))
                    {
                        int exitCode = RunApp(dotNetTools.GetToolPath($"Faithlife.PackageDiffTool.Tool/{packageDiffVersion}", "packagediff"),
                                              new AppRunnerSettings
                        {
                            Arguments         = new[] { "--verifyversion", "--verbose", packagePath },
                            IsExitCodeSuccess = x => x <= 2,                                             // don't fail on crash
                        });
                        hasBadPackageVersion = exitCode == 2;
                    }
                }
            });

            build.Target("publish")
            .Describe("Publishes NuGet packages and documentation")
            .DependsOn("clean", "package")
            .Does(() =>
            {
                if (packagePaths.Count == 0)
                {
                    throw new ApplicationException("No NuGet packages found.");
                }

                var trigger = triggerOption.Value;
                if (trigger == null)
                {
                    throw new ApplicationException("--trigger option required.");
                }

                bool shouldPublishPackages = trigger == "publish-package" || trigger == "publish-packages" || trigger == "publish-all";
                bool shouldPublishDocs     = trigger == "publish-docs" || trigger == "publish-all";

                var triggerMatch = s_triggerRegex.Match(trigger);
                if (triggerMatch.Success)
                {
                    var triggerName    = triggerMatch.Groups["name"].Value;
                    var triggerVersion = triggerMatch.Groups["version"].Value;
                    if (triggerName.Length == 0)
                    {
                        var mismatches = packagePaths.Where(x => GetPackageInfo(x).Version != triggerVersion).ToList();
                        if (mismatches.Count != 0)
                        {
                            throw new ApplicationException($"Trigger '{trigger}' doesn't match package version: {string.Join(", ", mismatches.Select(Path.GetFileName))}");
                        }
                    }
                    else
                    {
                        var matches = packagePaths.Where(x => $".{GetPackageInfo(x).Name}".EndsWith($".{triggerName}", StringComparison.OrdinalIgnoreCase)).ToList();
                        if (matches.Count == 0)
                        {
                            throw new ApplicationException($"Trigger '{trigger}' does not match any packages: {string.Join(", ", packagePaths.Select(Path.GetFileName))}");
                        }
                        if (matches.Count > 1)
                        {
                            throw new ApplicationException($"Trigger '{trigger}' matches multiple package(s): {string.Join(", ", matches.Select(Path.GetFileName))}");
                        }
                        if (GetPackageInfo(matches[0]).Version != triggerVersion)
                        {
                            throw new ApplicationException($"Trigger '{trigger}' doesn't match package version: {Path.GetFileName(matches[0])}");
                        }
                        packagePaths = matches;
                    }

                    shouldPublishPackages = true;
                    shouldPublishDocs     = !triggerMatch.Groups["suffix"].Success;
                }

                if (shouldPublishPackages && hasBadPackageVersion)
                {
                    throw new ApplicationException("Use suggested package version to publish.");
                }

                if (shouldPublishPackages || shouldPublishDocs)
                {
                    var docsSettings      = settings.DocsSettings;
                    bool shouldPushDocs   = false;
                    string cloneDirectory = null;
                    string repoDirectory  = null;
                    string gitBranchName  = null;

                    Credentials provideCredentials(string url, string usernameFromUrl, SupportedCredentialTypes types) =>
                    new UsernamePasswordCredentials
                    {
                        Username = docsSettings.GitLogin.Username ?? throw new ApplicationException("GitLogin has a null Username."),
                        Password = docsSettings.GitLogin.Password ?? throw new ApplicationException("GitLogin has a null Password."),
                    };

                    if (shouldPublishDocs && docsSettings != null)
                    {
                        if (docsSettings.GitLogin == null || docsSettings.GitAuthor == null)
                        {
                            throw new ApplicationException("GitLogin and GitAuthor must be set on DocsSettings.");
                        }

                        var gitRepositoryUrl = docsSettings.GitRepositoryUrl;
                        gitBranchName        = docsSettings.GitBranchName;

                        if (gitRepositoryUrl != null)
                        {
                            cloneDirectory = "docs_repo_" + Path.GetRandomFileName();
                            Repository.Clone(sourceUrl: gitRepositoryUrl, workdirPath: cloneDirectory,
                                             options: new CloneOptions {
                                BranchName = gitBranchName, CredentialsProvider = provideCredentials
                            });
                            repoDirectory = cloneDirectory;
                        }
                        else
                        {
                            repoDirectory = ".";
                        }

                        using (var repository = new Repository(repoDirectory))
                        {
                            if (gitRepositoryUrl != null)
                            {
                                if (gitBranchName == null)
                                {
                                    gitBranchName = repository.Head.FriendlyName;
                                }
                            }
                            else if (gitBranchName != null)
                            {
                                if (gitBranchName != repository.Head.FriendlyName)
                                {
                                    var branch = repository.Branches[gitBranchName] ?? repository.CreateBranch(gitBranchName);
                                    Commands.Checkout(repository, branch);
                                }
                            }
                            else
                            {
                                var branch = repository.Branches.FirstOrDefault(x => x.IsCurrentRepositoryHead);
                                if (branch == null)
                                {
                                    var autoBranchName = Environment.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH");
                                    if (autoBranchName == null)
                                    {
                                        throw new ArgumentException("Could not determine repository branch.");
                                    }

                                    branch = repository.Branches[autoBranchName] ?? repository.CreateBranch(autoBranchName);
                                    Commands.Checkout(repository, branch);
                                }
                                gitBranchName = branch.FriendlyName;
                            }

                            foreach (var projectName in packagePaths.Select(x => GetPackageInfo(x).Name))
                            {
                                string findAssembly(string name) =>
                                FindFiles($"tools/XmlDocTarget/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault() ??
                                FindFiles($"src/{name}/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault();

                                var assemblyPath = (docsSettings.FindAssembly ?? findAssembly)(projectName);
                                if (assemblyPath != null)
                                {
                                    RunApp(dotNetTools.GetToolPath($"xmldocmd/{xmlDocMarkdownVersion}"), assemblyPath,
                                           Path.Combine(repoDirectory, docsSettings.TargetDirectory ?? "docs"),
                                           "--source", $"{docsSettings.SourceCodeUrl}/{projectName}", "--newline", "lf", "--clean");
                                }
                                else
                                {
                                    Console.WriteLine($"Documentation not generated for {projectName}; assembly not found.");
                                }
                            }

                            shouldPushDocs = repository.RetrieveStatus().IsDirty;
                        }
                    }

                    if (shouldPublishPackages)
                    {
                        var projectUsesSourceLink = settings.ProjectUsesSourceLink;
                        foreach (var packagePath in packagePaths)
                        {
                            if (projectUsesSourceLink == null || projectUsesSourceLink(GetPackageInfo(packagePath).Name))
                            {
                                RunApp(dotNetTools.GetToolPath($"sourcelink/{sourceLinkVersion}"), "test", packagePath);
                            }
                        }

                        var nugetApiKey = settings.NuGetApiKey;
                        if (string.IsNullOrEmpty(nugetApiKey))
                        {
                            throw new ApplicationException("NuGetApiKey required to publish.");
                        }

                        foreach (var packagePath in packagePaths)
                        {
                            RunDotNet("nuget", "push", packagePath, "--source", nugetSource, "--api-key", nugetApiKey);
                        }
                    }

                    if (shouldPushDocs)
                    {
                        using (var repository = new Repository(repoDirectory))
                        {
                            Console.WriteLine("Publishing documentation changes.");
                            Commands.Stage(repository, "*");
                            var author = new Signature(docsSettings.GitAuthor.Name, docsSettings.GitAuthor.Email, DateTimeOffset.Now);
                            repository.Commit("Documentation updated.", author, author, new CommitOptions());
                            repository.Network.Push(repository.Network.Remotes["origin"],
                                                    $"refs/heads/{gitBranchName}", new PushOptions {
                                CredentialsProvider = provideCredentials
                            });
                        }
                    }

                    if (cloneDirectory != null)
                    {
                        // delete the cloned directory
                        foreach (var fileInfo in FindFiles(cloneDirectory, "**").Select(x => new FileInfo(x)).Where(x => x.IsReadOnly))
                        {
                            fileInfo.IsReadOnly = false;
                        }
                        Directory.Delete(cloneDirectory, recursive: true);
                    }
                }
                else
                {
                    Console.WriteLine("To publish to NuGet, push a matching git tag for the release.");
                }
            });

            string getPlatformArg()
            {
                string platformValue = platformOption.Value ?? settings?.SolutionPlatform;

                return(platformValue == null ? null : $"-p:Platform={platformValue}");
            }

            string getMaxCpuCountArg()
            {
                if (settings.MaxCpuCount != null)
                {
                    return($"-maxcpucount:{settings.MaxCpuCount}");
                }
                else if (msbuildSettings != null)
                {
                    return("-maxcpucount");
                }
                else
                {
                    return(null);
                }
            }

            IEnumerable <string> getExtraProperties(string target)
            {
                var pairs = settings.ExtraProperties?.Invoke(target);

                if (pairs != null)
                {
                    foreach (var pair in pairs)
                    {
                        yield return($"-p:{pair.Key}={pair.Value}");
                    }
                }
            }

            void runMSBuild(IEnumerable <string> arguments) => RunMSBuild(msbuildSettings, arguments);
        }
Example #19
0
        public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory)
        {
            if (isDirectory)
            {
                expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar;
            }

            string repoPath = InitNewRepository();

            using (var repo = new Repository(repoPath))
            {
                PopulateBasicRepository(repo);

                const string relativePathUpdated = "updated.txt";
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A");
                repo.Stage(relativePathUpdated);
                repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature);

                // Create conflicting change
                const string relativePathConflict = "conflict.txt";
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A");
                repo.Stage(relativePathConflict);
                repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature);

                // Create another branch
                repo.CreateBranch("newbranch");

                // Make an edit to conflict.txt and update.txt
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB");
                repo.Stage(relativePathUpdated);
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB");
                repo.Stage(relativePathConflict);

                repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature);

                // Checkout other branch
                repo.Checkout("newbranch");

                // Make alternate edits to conflict.txt and update.txt
                Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC");
                repo.Stage(relativePathUpdated);
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC");
                repo.Stage(relativePathConflict);
                repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature);

                // make conflicting change to conflict.txt
                Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD");
                repo.Stage(relativePathConflict);

                // Create ignored change
                string relativePathIgnore = Path.Combine("bin", "ignored.txt");
                Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file");

                // Create untracked change
                const string relativePathUntracked = "untracked.txt";
                Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file");

                bool   wasCalled = false;
                string actualNotificationPath         = string.Empty;
                CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None;

                CheckoutOptions options = new CheckoutOptions()
                {
                    OnCheckoutNotify    = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return(true); },
                    CheckoutNotifyFlags = notifyFlags,
                };

                Assert.Throws <CheckoutConflictException>(() => repo.Checkout("master", options));

                Assert.True(wasCalled);
                Assert.Equal(expectedNotificationPath, actualNotificationPath);
                Assert.Equal(notifyFlags, actualNotifyFlags);
            }
        }
Example #20
0
 public void CreatingABranchFromANonCommitObjectThrows()
 {
     using (var repo = new Repository(BareTestRepoPath))
     {
         const string name = "sorry-dude-i-do-not-do-blobs-nor-trees";
         Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "refs/tags/point_to_blob"));
         Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "53fc32d"));
         Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "0266163"));
     }
 }
Example #21
0
        /// <summary>
        /// Don't rename to OnSelectedFileChanged as that messes things up with NotifyPropertyChanged.Fody
        /// </summary>

/*
 *      private void WhenSelectedFileChanged()
 *      {
 *          var selectedFile = SelectedFile;
 *
 *          if (selectedFile == null)
 *          {
 *              return;
 *          }
 *
 *          string oldContentText;
 *          string newContentText;
 *          if (SelectedItemViewModel.Commit != null)
 *          {
 *              var commit = SelectedItemViewModel.Commit;
 *
 *              var oldContent = (Blob)commit?.Parents.FirstOrDefault()?[selectedFile]?.Target;
 *              var newContent = (Blob)commit?[selectedFile]?.Target;
 *
 *              oldContentText = oldContent?.GetContentText();
 *              newContentText = newContent?.GetContentText();
 *          }
 *          else
 *          {
 *              var oldContent = Repository.Lookup<Blob>(Repository.Index[selectedFile].Id);
 * //                var oldContent = (Blob)Branch.Tip[selectedFile]?.Target;
 *              oldContentText = oldContent?.GetContentText();
 *
 *              newContentText = File.ReadAllText(Path.Combine(Repository.Info.WorkingDirectory, selectedFile)).Replace("\r\n", "\n");
 *          }
 *
 *          SelectedFileContent = DiffLineGenerator.GenerateLineDiffs(oldContentText, newContentText);
 *      }
 *
 */
        public void CreateBranch(string branchName)
        {
            Repository.CreateBranch(branchName);
        }
Example #22
0
        public async Task Execute()
        {
            var directory = _options.Directory;

            if (string.IsNullOrWhiteSpace(directory))
            {
                _logger.LogDebug("Setting directory to current");
                directory = Directory.GetCurrentDirectory();
            }

            _logger.LogDebug("Checking for git repo");

            if (!Repository.IsValid(directory))
            {
                _logger.LogInformation($"{directory} is not a valid git repository");
                return;
            }

            if (_options.Interval < 10)
            {
                _logger.LogInformation("The defined interval can't be smaller than 10 seconds");
                return;
            }

            using var cts = new CancellationTokenSource();

            void cancelToken(object sender, ConsoleCancelEventArgs e)
            {
                if (cts.IsCancellationRequested)
                {
                    return;
                }

                _logger.LogDebug("Cancelled directory watcher");

                e.Cancel = true;
                Console.CancelKeyPress -= cancelToken;

                cts.Cancel();
            }

            Console.CancelKeyPress += cancelToken;

            using var repo = new Repository(directory);
            CheckOut(repo);

            var startBranch = repo.Head;

            switch (startBranch.FriendlyName)
            {
            case nameof(GitAutocommit):
            {
                _logger.LogInformation($"You're still on a {nameof(GitAutocommit)} branch.");
                _logger.LogInformation("This is most likely because a previous crash or unusual program termination. Please fix your repository first.");
                return;
            }

            case "master":
            {
                _logger.LogInformation("Warning: You're currently working on master branch!");
                break;
            }
            }

            var startCommit = startBranch.Tip;

            var branch = repo.Branches[nameof(GitAutocommit)];

            if (branch != null)
            {
                CreateBranch(repo, branch);
            }

            _logger.LogDebug("Creating auto commit branch");
            repo.CreateBranch(nameof(GitAutocommit));
            branch = repo.Branches[nameof(GitAutocommit)];

            _logger.LogDebug("Checking out auto commit branch");
            Commands.Checkout(repo, branch);

            var interval         = TimeSpan.FromSeconds(_options.Interval);
            var autoCommitAuthor = new Signature(nameof(GitAutocommit), "@" + nameof(GitAutocommit), DateTime.Now);

            _logger.LogDebug($"Checking repo changes with an interval of {_options.Interval} seconds");
            _logger.LogInformation($"Monitoring {directory} for changes");

            await CommitChanges(interval, repo, autoCommitAuthor, cts);

            var currentHead = repo.Head.Tip;
            var hasChanges  = currentHead != startBranch.Tip;

            string msg = ResolveCommitMessage(hasChanges);

            _logger.LogInformation("Checking out " + startBranch.FriendlyName);
            Commands.Checkout(repo, startBranch);

            if (hasChanges)
            {
                Commit(repo, startCommit, currentHead, msg);
            }

            _logger.LogInformation("Removing auto commit branch");
            repo.Branches.Remove(branch);

            if (_options.AutoPush != null)
            {
                AutoPush(repo, startBranch);
            }


            _logger.LogInformation("Finished auto committing");
        }
Example #23
0
        private void ConstructRebaseTestRepository(Repository repo, string attributes = "* text=auto", string lineEnding = "\r\n")
        {
            // Constructs a graph that looks like:
            //                         * -- * -- *   (modifications to c.txt)
            //                        /          |
            //                       /           T2
            //                      /
            //           * -- * -- *                 (modifications to b.txt)
            //          /          |
            //         /           T1
            //        /
            // *--*--*--*--*--*----
            //       |        |    \
            //       M1       M2    \
            //                       ---*
            //                          |
            //                          C1
            const string fileContentA1 = "A1";

            const string fileContentB1 = "B1";
            const string fileContentB2 = "B2";
            const string fileContentB3 = "B3";
            const string fileContentB4 = "B4";

            const string fileContentC1 = "C1";
            const string fileContentC2 = "C2";
            const string fileContentC3 = "C3";
            const string fileContentC4 = "C4";

            const string fileContentD1 = "D1";
            const string fileContentD2 = "D2";
            const string fileContentD3 = "D3";

            string workdir = repo.Info.WorkingDirectory;
            Commit commit  = null;

            CreateAttributesFile(repo, attributes);

            Commands.Stage(repo, ".gitattributes");
            commit = repo.Commit("setup", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathA, fileContentA1);
            Commands.Stage(repo, filePathA);
            commit = repo.Commit("commit 1", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathB, fileContentB1);
            Commands.Stage(repo, filePathB);
            commit = repo.Commit("commit 2", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathC, fileContentC1);
            Commands.Stage(repo, filePathC);
            commit = repo.Commit("commit 3", Constants.Signature, Constants.Signature, new CommitOptions());

            Branch masterBranch1 = repo.CreateBranch(masterBranch1Name, commit);

            Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2));
            Commands.Stage(repo, filePathB);
            commit = repo.Commit("commit 4", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3));
            Commands.Stage(repo, filePathB);
            commit = repo.Commit("commit 5", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3, fileContentB4));
            Commands.Stage(repo, filePathB);
            commit = repo.Commit("commit 6", Constants.Signature, Constants.Signature, new CommitOptions());

            repo.CreateBranch(topicBranch1Name, commit);

            Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2));
            Commands.Stage(repo, filePathC);
            commit = repo.Commit("commit 7", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3));
            Commands.Stage(repo, filePathC);
            commit = repo.Commit("commit 8", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3, fileContentC4));
            Commands.Stage(repo, filePathC);
            commit = repo.Commit("commit 9", Constants.Signature, Constants.Signature, new CommitOptions());

            repo.CreateBranch(topicBranch2Name, commit);

            repo.Checkout(masterBranch1.Tip);
            Touch(workdir, filePathD, fileContentD1);
            Commands.Stage(repo, filePathD);
            commit = repo.Commit("commit 10", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2));
            Commands.Stage(repo, filePathD);
            commit = repo.Commit("commit 11", Constants.Signature, Constants.Signature, new CommitOptions());

            Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2, fileContentD3));
            Commands.Stage(repo, filePathD);
            commit = repo.Commit("commit 12", Constants.Signature, Constants.Signature, new CommitOptions());

            repo.CreateBranch(masterBranch2Name, commit);

            // Create commit / branch that conflicts with T1 and T2
            Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2 + fileContentB3 + fileContentB4));
            Commands.Stage(repo, filePathB);
            commit = repo.Commit("commit 13", Constants.Signature, Constants.Signature, new CommitOptions());
            repo.CreateBranch(conflictBranch1Name, commit);
        }
Example #24
0
 public void CreateBranch(string branchName)
 {
     LibGit2Sharp.Commands.Checkout(_repo, _repo.CreateBranch(branchName));
 }
Example #25
0
        static void Main1(string[] args)
        {
            var server   = @"";
            var dbName   = ""; // "ZENITH_PRODUCTION";
            var user     = "******";
            var password = "";

            var workingDir = AppDomain.CurrentDomain.BaseDirectory;
            var outputDir  = System.IO.Path.Combine(workingDir, directory);

            if (!System.IO.Directory.Exists(outputDir))
            {
                System.IO.Directory.CreateDirectory(outputDir);
            }


            /// connection
            var conn = new ServerConnection(server, user, password);
            //conn.BeginTransaction();
            //conn.CommitTransaction();

            // server
            Server srv = new Server(conn);

            // database
            var db = srv.Databases[dbName];

            db.CompatibilityLevel = CompatibilityLevel.Version100;

            // scripter engine
            Scripter scp = new Scripter(srv);

            #region Scripter Options
            scp.Options.NoCollation         = true;
            scp.Options.NoCommandTerminator = true;
            // only schema
            scp.Options.ScriptSchema = true;
            scp.Options.ScriptData   = false;
            // no GO's
            scp.Options.NoCommandTerminator = false;
            // without output stream (all objects at once)
            scp.Options.ToFileOnly = true;
            // objects defaults
            scp.Options.AllowSystemObjects = false;
            scp.Options.Permissions        = true;
            scp.Options.SchemaQualify      = true;
            scp.Options.AnsiFile           = true;
            scp.Options.AnsiPadding        = false;

            scp.Options.SchemaQualifyForeignKeysReferences = true;
            scp.Options.DriAllConstraints   = true;
            scp.Options.DriIndexes          = true;
            scp.Options.DriClustered        = true;
            scp.Options.DriNonClustered     = true;
            scp.Options.Indexes             = true;
            scp.Options.NonClusteredIndexes = true;
            scp.Options.ClusteredIndexes    = true;
            scp.Options.FullTextIndexes     = true;

            scp.Options.EnforceScriptingOptions = true;
            /// case of our tests
            scp.Options.WithDependencies = false;
            #endregion


            var values        = db.Tables["SAVGLOBALIZATION_VALUES"];
            var globalization = db.Tables["SAVGLOBALIZATION_VALUES"];



            using (var repo = new Repository(outputDir))
            {
                var branchName = GetCurrentBranchName();
                var branch     = repo.CreateBranch(branchName);
                var master     = repo.Branches["master"];
                Commands.Checkout(repo, branch);

                // remove all .sql files before start
                foreach (var file in System.IO.Directory.GetFiles(outputDir, "*.SQL"))
                {
                    System.IO.File.Delete(file);
                }

                scp.Options.ScriptSchema = false;
                scp.Options.ScriptData   = true;
                scp.ExportFilesToScriptAndManifest(new[] { values.Urn, globalization.Urn }, "DataManifest.txt", null, outputDir: outputDir);

                scp.Options.ScriptSchema = true;
                scp.Options.ScriptData   = false;

                // prepare tables to export
                var tables = db.Tables.Cast <Table>()
                             .Where(tbl => !tbl.IsSystemObject)
                             .Select(n => n.Urn).ToArray();

                // Export it as manifest
                HashSet <Urn> hash = new HashSet <Urn>();

                scp.FilterCallbackFunction = FilterTablesOnly;
                scp.ExportFilesToScriptAndManifest(tables, "TableManifest.txt", hash, outputDir: outputDir);

                // Export tables to script and manifest
                var views = db.Views.Cast <View>()
                            .Where(vw => !vw.IsSystemObject)
                            .Select(n => n.Urn).ToArray();

                // Export views to script and manifest
                scp.FilterCallbackFunction = FilterViewsOnly;
                scp.ExportFilesToScriptAndManifest(views, "ViewManifest.txt", hash, outputDir: outputDir);


                Commands.Stage(repo, "*");

                Signature author    = new Signature("Felipe Correa", "*****@*****.**", DateTime.Now);
                Signature committer = author;

                var committed = repo.Commit(string.Format("Adds {0} ", branchName), author, committer);


                Commands.Checkout(repo, master);
                var result = repo.Merge(branch, author);

                repo.Branches.Remove(branch);
            }
        }
Example #26
0
        public void CheckStatus(bool forceUpdate = false)
        {
            var mustClone = false;

            Log.KeyValuePair(GetType().Name, $"Repository: {Configuration.Url}", Message.EContentType.MoreInfo);
            Log.Info(LocalStoragePath);

            try
            {
                // Try to create the local git clone storage, if not present;
                Directory.CreateDirectory(LocalStoragePath);

                Credentials GitHubCredentialsProvider(string url, string usernameFromUrl,
                                                      SupportedCredentialTypes types)
                {
                    return(new UsernamePasswordCredentials {
                        Username = Configuration.Token, Password = ""
                    });
                }

                var pullOptions = new PullOptions
                {
                    MergeOptions = new MergeOptions {
                        FastForwardStrategy = FastForwardStrategy.Default
                    },
                    FetchOptions = new FetchOptions
                    {
                        CredentialsProvider = GitHubCredentialsProvider
                    }
                };

                var cloneOptions = new CloneOptions
                {
                    CredentialsProvider = GitHubCredentialsProvider
                };

                var signature = new Signature(Host.ApplicationAssemblyName, "*****@*****.**", DateTimeOffset.Now);

                try
                {
                    // Is it initialized?
                    using var localRepo = new Repository(LocalStoragePath);

                    if (Configuration.Branch != null)
                    {
                        var currentBranch = localRepo.Branches[Configuration.Branch];

                        if (currentBranch == null)
                        {
                            localRepo.CreateBranch(Configuration.Branch);
                            currentBranch = localRepo.Branches[Configuration.Branch];
                        }

                        if (currentBranch.FriendlyName != Configuration.Branch)
                        {
                            currentBranch = Commands.Checkout(localRepo, currentBranch);
                        }
                    }

                    Log.Add(LocalStoragePath);

                    var status = localRepo.RetrieveStatus();

                    // Always try to Fetch changes.
                    var remote   = localRepo.Network.Remotes.FirstOrDefault();
                    var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification).ToList();
                    Commands.Fetch(localRepo, remote.Name, refSpecs, pullOptions.FetchOptions, null);

                    try
                    {
                        var mergeResult = Commands.Pull(localRepo, signature, pullOptions);

                        if (mergeResult.Status == MergeStatus.UpToDate)
                        {
                            Log.KeyValuePair(GetType().Name, "Repository is up-to-date",
                                             Message.EContentType.MoreInfo);
                        }
                        else
                        {
                            Log.KeyValuePair(GetType().Name,
                                             mergeResult?.Commit?.Message.Replace("\n", " | ") ?? "Fetch/Pull finished.",
                                             Message.EContentType.MoreInfo);
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Add(e);
                    }

                    // Commit/push stragglers.

                    if (status.IsDirty)
                    {
                        Log.KeyValuePair(GetType().Name, $"{status.Count()} uncommitted change(s)", Message.EContentType.MoreInfo);


                        //try
                        //{
                        //    var commitOptions = new CommitOptions();
                        //    localRepo.Commit(Host.ApplicationAssemblyName + " automatic sync", signature, signature, commitOptions);
                        //}
                        //catch (Exception) { }

                        //var targetSpec = @"refs/heads/" + Configuration.Branch.Split('/')[1];

                        //localRepo.Network.Push(remote, targetSpec, new PushOptions {CredentialsProvider = GitHubCredentialsProvider});
                    }
                }
                catch (RepositoryNotFoundException e)
                {
                    Log.KeyValuePair(GetType().Name, "Local repo not found. Attempting to create.",
                                     Message.EContentType.Maintenance);
                    mustClone = true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }

                if (!mustClone)
                {
                    return;
                }

                try
                {
                    Log.KeyValuePair("Cloning", Configuration.Url, Message.EContentType.MoreInfo);
                    Log.KeyValuePair("To", LocalStoragePath, Message.EContentType.MoreInfo);

                    // Easy. Let's try to clone from source.
                    Repository.Clone(Configuration.Url, LocalStoragePath, cloneOptions);

                    Log.KeyValuePair("Status", "Success", Message.EContentType.MoreInfo);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
Example #27
0
        public void ConflictingMergeReposBinary()
        {
            const string firstBranchFileName = "first branch file.bin";
            const string secondBranchFileName = "second branch file.bin";
            const string sharedBranchFileName = "first+second branch file.bin";

            string path = CloneStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var firstBranch = repo.CreateBranch("FirstBranch");
                firstBranch.Checkout();

                // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit).
                AddFileCommitToRepo(repo, sharedBranchFileName);

                var secondBranch = repo.CreateBranch("SecondBranch");
                // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one).
                AddFileCommitToRepo(repo, firstBranchFileName);
                AddFileCommitToRepo(repo, sharedBranchFileName, "\0The first branches comment\0");  // Change file in first branch

                secondBranch.Checkout();
                // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit).
                AddFileCommitToRepo(repo, secondBranchFileName);
                AddFileCommitToRepo(repo, sharedBranchFileName, "\0The second branches comment\0");  // Change file in second branch

                MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature);

                Assert.Equal(MergeStatus.Conflicts, mergeResult.Status);

                Assert.Equal(1, repo.Index.Conflicts.Count());

                Conflict conflict = repo.Index.Conflicts.First();

                var changes = repo.Diff.Compare(repo.Lookup<Blob>(conflict.Theirs.Id), repo.Lookup<Blob>(conflict.Ours.Id));

                Assert.True(changes.IsBinaryComparison);
            }
        }
Example #28
0
        public static bool Run(CompressimagesParameters parameters, ICollector <CompressImagesMessage> compressImagesMessages, ILogger logger)
        {
            var storageAccount = CloudStorageAccount.Parse(Common.KnownEnvironmentVariables.AzureWebJobsStorage);
            var paidPlan       = PaidPlan(storageAccount, parameters.RepoOwner);
            CredentialsHandler credentialsProvider =
                (url, user, cred) =>
                new UsernamePasswordCredentials {
                Username = KnownGitHubs.Username, Password = parameters.Password
            };

            // clone
            var cloneOptions = new CloneOptions
            {
                CredentialsProvider = credentialsProvider,
            };

            Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions);

            var repo           = new Repository(parameters.LocalPath);
            var remote         = repo.Network.Remotes["origin"];
            var isWikiCompress = parameters.CloneUrl.EndsWith(".wiki.git");

            // check if we have the branch already or this is empty repo
            try
            {
                if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false)
                {
                    logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                    return(false);
                }
            }
            catch (Exception e)
            {
                // log + ignore
                logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
            }

            // check if the branch exists and has been modified by the user
            if (parameters.IsRebase && repo.Branches[$"refs/remotes/origin/{KnownGitHubs.BranchName}"].Tip.Author.Name != KnownGitHubs.ImgBotLogin)
            {
                logger.LogInformation("CompressImagesFunction: imgbot branch has been modified by the user.");
                return(false);
            }

            // check if we should switch away from the default branch
            if (!isWikiCompress && parameters.Settings != null && !string.IsNullOrEmpty(parameters.Settings.DefaultBranchOverride))
            {
                logger.LogInformation(
                    "CompressImagesFunction: default branch override for {Owner}/{RepoName} is {DefaultBranchOverride}",
                    parameters.RepoOwner,
                    parameters.RepoName,
                    parameters.Settings.DefaultBranchOverride);

                var baseBranch = repo.Branches[$"refs/remotes/origin/{parameters.Settings.DefaultBranchOverride}"];
                if (baseBranch == null)
                {
                    logger.LogWarning(
                        "CompressImagesFunction: default branch ({DefaultBranchOverride}) not found for {Owner}/{RepoName}",
                        parameters.Settings.DefaultBranchOverride,
                        parameters.RepoOwner,
                        parameters.RepoName);
                    return(false);
                }

                Commands.Checkout(repo, baseBranch);
            }

            var repoConfiguration = new RepoConfiguration();

            try
            {
                // see if .imgbotconfig exists in repo root
                var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig");
                if (!string.IsNullOrEmpty(repoConfigJson))
                {
                    repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson);

                    // for now we are not adding the labels functionality || repoConfiguration.Labels.Any() TODO: add it when adding the labels feature
                    if (paidPlan && (repoConfiguration.PrBody != null || repoConfiguration.PrTitle != null))
                    {
                        var settingsTable = storageAccount.CreateCloudTableClient().GetTableReference("settings");

                        // Labels = repoConfiguration.Labels TODO: add it when adding the labels feature
                        var settings = new Common.TableModels.Settings(
                            parameters.CompressImagesMessage.InstallationId.ToString(),
                            parameters.CompressImagesMessage.RepoName)
                        {
                            PrBody  = repoConfiguration.PrBody,
                            PrTitle = repoConfiguration.PrTitle,
                        };

                        settingsTable.ExecuteAsync(TableOperation.InsertOrReplace(settings)).Wait();
                    }
                }
            }
            catch
            {
                // ignore
            }

            // Add new compressMessage if we should compress Wiki
            if (repoConfiguration.CompressWiki && isWikiCompress == false)
            {
                logger.LogInformation("CompressImagesFunction: Adding Wiki image compression to queue for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                compressImagesMessages.Add(new CompressImagesMessage()
                {
                    InstallationId = parameters.CompressImagesMessage.InstallationId,
                    RepoName       = parameters.CompressImagesMessage.RepoName,
                    Owner          = parameters.RepoOwner,
                    CloneUrl       = $"https://github.com/{parameters.RepoOwner}/{parameters.RepoName}.wiki.git"
                });
            }

            if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false)
            {
                logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                return(false);
            }

            // Should not create branch if we are compressing Wiki or performing rebase
            if (isWikiCompress == false && !parameters.IsRebase)
            {
                // check out the branch
                repo.CreateBranch(KnownGitHubs.BranchName);
                var branch = Commands.Checkout(repo, KnownGitHubs.BranchName);
            }
            else if (parameters.IsRebase)
            {
                // if rebasing, fetch the branch
                var refspec = string.Format("{0}:{0}", KnownGitHubs.BranchName);
                Commands.Fetch(repo, "origin", new List <string> {
                    refspec
                }, null, "fetch");
            }

            // reset any mean files
            repo.Reset(ResetMode.Mixed, repo.Head.Tip);

            // optimize images
            var imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration);

            var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression);

            if (optimizedImages.Length == 0)
            {
                return(false);
            }

            if (!Threshold.MeetsThreshold(repoConfiguration, optimizedImages))
            {
                logger.LogInformation($"Did not meet threshold. {parameters.RepoOwner}/{parameters.RepoName}");
                return(false);
            }

            // create commit message based on optimizations
            foreach (var image in optimizedImages)
            {
                Commands.Stage(repo, image.OriginalPath);
            }

            var commitMessage = CommitMessage.Create(optimizedImages);
            var signature     = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now);

            repo.Commit(commitMessage, signature, signature);

            if (parameters.IsRebase)
            {
                var baseBranch = repo.Head;
                var newCommit  = baseBranch.Tip;

                // we need to reset the default branch so that we can
                // rebase to it later.
                repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1));

                Commands.Checkout(repo, KnownGitHubs.BranchName);

                // reset imgbot branch removing old commit
                repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1));

                // cherry-pick
                var cherryPickOptions = new CherryPickOptions()
                {
                    MergeFileFavor = MergeFileFavor.Theirs,
                };
                var cherryPickResult = repo.CherryPick(newCommit, signature, cherryPickOptions);

                if (cherryPickResult.Status == CherryPickStatus.Conflicts)
                {
                    var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions()
                    {
                    });
                    foreach (var item in status)
                    {
                        if (item.State == FileStatus.Conflicted)
                        {
                            Commands.Stage(repo, item.FilePath);
                        }
                    }

                    repo.Commit(commitMessage, signature, signature);
                }

                // rebase
                var rebaseOptions = new RebaseOptions()
                {
                    FileConflictStrategy = CheckoutFileConflictStrategy.Theirs,
                };

                var rebaseResult = repo.Rebase.Start(repo.Head, baseBranch, null, new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions);

                while (rebaseResult.Status == RebaseStatus.Conflicts)
                {
                    var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions()
                    {
                    });
                    foreach (var item in status)
                    {
                        if (item.State == FileStatus.Conflicted)
                        {
                            if (imagePaths.Contains(Path.Combine(parameters.LocalPath, item.FilePath)))
                            {
                                Commands.Stage(repo, item.FilePath);
                            }
                            else
                            {
                                Commands.Remove(repo, item.FilePath);
                            }
                        }
                    }

                    rebaseResult = repo.Rebase.Continue(new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions);
                }
            }

            // We just made a normal commit, now we are going to capture all the values generated from that commit
            // then rewind and make a signed commit
            var commitBuffer = Commit.CreateBuffer(
                repo.Head.Tip.Author,
                repo.Head.Tip.Committer,
                repo.Head.Tip.Message,
                repo.Head.Tip.Tree,
                repo.Head.Tip.Parents,
                true,
                null);

            var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword);

            repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha);
            var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData);

            repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep);

            // Should use "master" if we are compressing Wiki
            if (isWikiCompress)
            {
                var branchAgain = Commands.Checkout(repo, "master");
            }
            else
            {
                var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName);
            }

            repo.Reset(ResetMode.Hard, commitToKeep.Sha);

            // verify images are not corrupted by reading from git
            // see https://github.com/dabutvin/ImgBot/issues/273
            try
            {
                foreach (var image in optimizedImages)
                {
                    if (image.OriginalPath.EndsWith(".svg"))
                    {
                        // do not use ImageMagick to verify SVGs
                        continue;
                    }

                    new MagickImage(image.OriginalPath).Dispose();
                }
            }
            catch (MagickErrorException)
            {
                logger.LogError("Corrupt images after reset!");
                return(false);
            }

            // push to GitHub
            if (isWikiCompress)
            {
                repo.Network.Push(remote, "refs/heads/master", new PushOptions
                {
                    CredentialsProvider = credentialsProvider,
                });
            }
            else
            {
                var refs = $"refs/heads/{KnownGitHubs.BranchName}";
                if (parameters.IsRebase)
                {
                    refs = refs.Insert(0, "+");
                }
                logger.LogInformation("refs: {refs}", refs);

                repo.Network.Push(remote, refs, new PushOptions
                {
                    CredentialsProvider = credentialsProvider,
                });
            }

            try
            {
                Directory.Delete(parameters.LocalPath, true);
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Delete issue with repository {parameters.LocalPath}");
            }

            return(true);
        }
        public SourceControlResult SyncLocalRepository(string repoDir, string[] branchMatchers)
        {
            branchMatchers = branchMatchers ?? new string[0];

            using (var repo = new Repository(repoDir))
            {
                FetchFromAllRemotes(repo);

                var branchesToProcess             = FilterBranchesByMatchers(repo.Branches.ToList(), branchMatchers);
                var branchesToProcessInitialCount = branchesToProcess.Count;
                var branchesToProcessCurrentCount = 0;

                _logger.Information(
                    "Found {Count} branch(es) starting with at least of the following matchers {BranchMatchers}...",
                    branchesToProcess.Count, branchMatchers);

                // Prepare for pull
                var signature   = new Signature(_userInfo.Username, _userInfo.Email, DateTimeOffset.Now);
                var pullOptions = new PullOptions
                {
                    FetchOptions = new FetchOptions
                    {
                        CredentialsProvider = (url, usernameFromUrl, types) => _credentials
                    },
                    MergeOptions = new MergeOptions
                    {
                        FastForwardStrategy = FastForwardStrategy.Default
                    }
                };

                var localTrackingBranches = branchesToProcess
                                            .Where(branch => !branch.IsRemote)
                                            .Where(branch => !branch.FriendlyName.EndsWith("/HEAD"))
                                            .Where(branch => branch.IsTracking)
                                            .ToList();

                var remoteBranches = branchesToProcess
                                     .Where(branch => branch.IsRemote)
                                     .Where(branch => !branch.FriendlyName.EndsWith("/HEAD"))
                                     // Where local branch tracking this remote does not exist
                                     .Where(branch =>
                                            !localTrackingBranches.Any(x => x.TrackedBranch.FriendlyName.Equals(branch.FriendlyName)))
                                     .ToList();

                // Checkout branches that do not have local branches that track remotes
                branchesToProcess = branchesToProcess.Except(remoteBranches).ToList();
                foreach (var branch in remoteBranches)
                {
                    branchesToProcessCurrentCount++;
                    var localBranchName = branch.UpstreamBranchCanonicalName.Substring("refs/heads/".Length,
                                                                                       branch.UpstreamBranchCanonicalName.Length - "refs/heads/".Length);

                    _logger.Information("Branch {BranchName} does not exist locally. Creating", localBranchName);
                    var localBranch = repo.CreateBranch(localBranchName, branch.Tip);
                    repo.Branches.Update(localBranch, b => b.TrackedBranch = branch.CanonicalName);

                    _logger.Information("Checking out [{Index}/{Count}] {BranchName}...", branchesToProcessCurrentCount,
                                        branchesToProcessInitialCount, localBranch.FriendlyName);
                    Commands.Checkout(repo, localBranch,
                                      new CheckoutOptions {
                        CheckoutModifiers = CheckoutModifiers.Force
                    });
                }

                // Checkout and pull local branches that track remotes
                branchesToProcess = branchesToProcess.Except(localTrackingBranches).ToList();
                foreach (var branch in localTrackingBranches)
                {
                    _logger.Information("Checking out [{Index}/{Count}] {BranchName}...", branchesToProcessCurrentCount,
                                        branchesToProcessInitialCount, branch.FriendlyName);
                    var checkoutOptions = new CheckoutOptions {
                        CheckoutModifiers = CheckoutModifiers.Force
                    };
                    Commands.Checkout(repo, branch, checkoutOptions);

                    _logger.Information("Pulling {BranchName}...", branch.FriendlyName);
                    Commands.Pull(repo, signature, pullOptions);
                }

                if (branchesToProcess.Any())
                {
                    _logger.Warning("Found {Count} branches that weren't processed. {Branches}",
                                    branchesToProcess.Count, string.Join(",", branchesToProcess.Select(x => x.FriendlyName)));
                }
            }

            return(SourceControlResultFactory.MakeSuccessful);
        }
Example #30
0
        private Branch CheckoutDeploymentManifest(Repository gitRepository, ApplicationSourceRepository repository,
                                                  UsernamePasswordGitCredentials credentials)
        {
            _log.LogInformation("CheckoutDeploymentManifest ...");

            var branchNames = gitRepository.Branches.Select(x => x.CanonicalName).ToList();

            var branch       = gitRepository.Branches.FirstOrDefault(b => b.FriendlyName == repository.Ref);
            var originBranch =
                gitRepository.Branches.FirstOrDefault(b => b.FriendlyName == $"origin/{repository.Ref}");

            if (branch != null || originBranch != null)
            {
                if (branch == null)
                {
                    // checkout branch from origin and make sure we are tracking the remote branchb
                    branch = gitRepository.CreateBranch(repository.Ref, originBranch.Tip);
                    branch = gitRepository.Branches.Update(branch,
                                                           b => b.TrackedBranch = originBranch.CanonicalName
                                                           );
                }

                // we already have a local copy of the branch, make sure it's the current head (if not switch to it)
                if (branch.Tip != gitRepository.Head.Tip)
                {
                    // switch to selected branch
                    _log.LogInformation("Switching from branch {currentBranch} to {requestedBranch}",
                                        gitRepository.Head.CanonicalName, branch.CanonicalName);
                    Commands.Checkout(gitRepository, branch);
                }

                var currentHash = gitRepository.Head.Tip.Sha;

                _log.LogInformation("Fetching latest sources for {branch} [{currentHash}] ...",
                                    branch.CanonicalName, currentHash);

                // TODO maybe this needs to be a fetch
                Commands.Pull(gitRepository,
                              new Signature("rig-deploy-bot", "*****@*****.**", DateTimeOffset.Now),
                              new PullOptions()
                {
                    FetchOptions = new FetchOptions()
                    {
                        Prune = true,
                        CredentialsProvider = (url, fromUrl, types) => new UsernamePasswordCredentials()
                        {
                            Username = credentials.Username,
                            Password = credentials.Password
                        }
                    },
                    MergeOptions = new MergeOptions()
                    {
                        FastForwardStrategy = FastForwardStrategy.FastForwardOnly
                    }
                });

                if (gitRepository.Head.Tip.Sha != currentHash)
                {
                    _log.LogInformation("Branch changed, triggered application refresh");
                }
            }
            else
            {
                var tag = gitRepository.Tags[repository.Ref];
                if (tag != null)
                {
                    var currentHash = tag.Target.Sha;

                    Commands.Fetch(
                        gitRepository,
                        "origin",
                        Enumerable.Empty <string>(),
                        new FetchOptions()
                    {
                        Prune = true,
                        CredentialsProvider = (url, fromUrl, types) => new UsernamePasswordCredentials()
                        {
                            Username = credentials.Username,
                            Password = credentials.Password
                        }
                    },
                        null);


                    tag = gitRepository.Tags[repository.Ref];

                    if (currentHash != tag.Target.Sha)
                    {
                        _log.LogInformation("Tag hash changed, triggered application refresh.");
                    }
                }
                else
                {
                    // its a git commit hash
                    var currentHash = gitRepository.Head.Tip.Sha;

                    if (currentHash != repository.Ref)
                    {
                        _log.LogInformation(
                            $"Current hash [{currentHash}] is not requested hash [{repository.Ref}], git checkout of commit will be triggered.");

                        Commands.Checkout(gitRepository, repository.Ref);
                    }
                }
            }

            return(branch);
        }
Example #31
0
        public static bool Run(CompressimagesParameters parameters, ILogger logger)
        {
            CredentialsHandler credentialsProvider =
                (url, user, cred) =>
                new UsernamePasswordCredentials {
                Username = KnownGitHubs.Username, Password = parameters.Password
            };

            // clone
            var cloneOptions = new CloneOptions
            {
                CredentialsProvider = credentialsProvider,
            };

            Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions);

            var repo   = new Repository(parameters.LocalPath);
            var remote = repo.Network.Remotes["origin"];

            // check if we have the branch already or this is empty repo
            try
            {
                if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false)
                {
                    logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                    return(false);
                }

                if (repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}"))
                {
                    logger.LogInformation("CompressImagesFunction: branch already exists for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                    return(false);
                }
            }
            catch (Exception e)
            {
                // log + ignore
                logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
            }

            var repoConfiguration = new RepoConfiguration();

            try
            {
                // see if .imgbotconfig exists in repo root
                var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig");
                if (!string.IsNullOrEmpty(repoConfigJson))
                {
                    repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson);
                }
            }
            catch
            {
                // ignore
            }

            if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false)
            {
                logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                return(false);
            }

            // check out the branch
            repo.CreateBranch(KnownGitHubs.BranchName);
            var branch = Commands.Checkout(repo, KnownGitHubs.BranchName);

            // reset any mean files
            repo.Reset(ResetMode.Mixed, repo.Head.Tip);

            // optimize images
            var imagePaths      = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration);
            var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression);

            if (optimizedImages.Length == 0)
            {
                return(false);
            }

            // create commit message based on optimizations
            foreach (var image in optimizedImages)
            {
                Commands.Stage(repo, image.OriginalPath);
            }

            var commitMessage = CommitMessage.Create(optimizedImages);
            var signature     = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now);

            repo.Commit(commitMessage, signature, signature);

            // We just made a normal commit, now we are going to capture all the values generated from that commit
            // then rewind and make a signed commit
            var commitBuffer = Commit.CreateBuffer(
                repo.Head.Tip.Author,
                repo.Head.Tip.Committer,
                repo.Head.Tip.Message,
                repo.Head.Tip.Tree,
                repo.Head.Tip.Parents,
                true,
                null);

            var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword);

            repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha);
            var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData);

            repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep);
            var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName);

            repo.Reset(ResetMode.Hard, commitToKeep.Sha);

            // verify images are not corrupted by reading from git
            // see https://github.com/dabutvin/ImgBot/issues/273
            try
            {
                foreach (var image in optimizedImages)
                {
                    new MagickImage(image.OriginalPath).Dispose();
                }
            }
            catch (MagickErrorException)
            {
                logger.LogError("Corrupt images after reset!");
                return(false);
            }

            // push to GitHub
            repo.Network.Push(remote, $"refs/heads/{KnownGitHubs.BranchName}", new PushOptions
            {
                CredentialsProvider = credentialsProvider,
            });

            return(true);
        }
Example #32
0
        private static void CloneAndPullRepo(int i, List <RepositoryModel> listRepositories, string userName, string password)
        {
            var stopWatch = Stopwatch.StartNew();

            var repoModel = listRepositories[i];

            var repoLink = repoModel.links.clone.FirstOrDefault()?.href;

            var repoFolder = Path.Combine(RepoBaseFolder, repoModel.full_name);

            var repoFolderInfo = new DirectoryInfo(repoFolder);

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write($"{i + 1}.");
            Console.ResetColor();

            Console.Write($" {repoLink} > {repoFolder}");

            if (!repoFolderInfo.Exists)
            {
                Repository.Clone(repoLink, repoFolder, new CloneOptions
                {
                    CredentialsProvider = (s, fromUrl, types) => new UsernamePasswordCredentials
                    {
                        Username = userName,
                        Password = password
                    }
                });
            }

            var repo = new Repository(repoFolder);

            var branches = repo.Branches;

            if (repoFolderInfo.Exists)
            {
                stopWatch.Stop();

                Console.Write($"[{branches.Count()} Branches]");

                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.Write($" [{stopWatch.Elapsed.TotalSeconds} s]");

                Console.ForegroundColor = ConsoleColor.Magenta;
                Console.WriteLine(" [Skipped]");
                Console.ResetColor();

                return;
            }

            foreach (var branch in branches)
            {
                if (!branch.IsRemote)
                {
                    continue;
                }

                var pullBranch = repo.CreateBranch(branch.FriendlyName, branch.Tip);

                var pulledBranch = repo.Branches.Update(pullBranch,
                                                        b => { b.TrackedBranch = branch.CanonicalName; });
            }

            stopWatch.Stop();

            stopWatch.Stop();

            Console.Write($"[{branches.Count()} Branches]");

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine($" [{stopWatch.Elapsed.TotalSeconds} s]");

            Console.ResetColor();
        }
        public void CanCommitALittleBit()
        {
            string repoPath = InitNewRepository();

            var identity = Constants.Identity;

            using (var repo = new Repository(repoPath, new RepositoryOptions {
                Identity = identity
            }))
            {
                string dir = repo.Info.Path;
                Assert.True(Path.IsPathRooted(dir));
                Assert.True(Directory.Exists(dir));

                const string relativeFilepath = "new.txt";
                string       filePath         = Touch(repo.Info.WorkingDirectory, relativeFilepath, "null");
                repo.Stage(relativeFilepath);
                File.AppendAllText(filePath, "token\n");
                repo.Stage(relativeFilepath);

                Assert.Null(repo.Head[relativeFilepath]);

                var author = Constants.Signature;

                const string shortMessage  = "Initial egotistic commit";
                const string commitMessage = shortMessage + "\n\nOnly the coolest commits from us";

                var before = DateTimeOffset.Now.TruncateMilliseconds();

                Commit commit = repo.Commit(commitMessage, author, author);

                AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n");
                AssertBlobContent(commit[relativeFilepath], "nulltoken\n");

                Assert.Equal(0, commit.Parents.Count());
                Assert.False(repo.Info.IsHeadUnborn);

                // Assert a reflog entry is created on HEAD
                Assert.Equal(1, repo.Refs.Log("HEAD").Count());
                var reflogEntry = repo.Refs.Log("HEAD").First();

                Assert.Equal(identity.Name, reflogEntry.Committer.Name);
                Assert.Equal(identity.Email, reflogEntry.Committer.Email);

                var now = DateTimeOffset.Now;
                Assert.InRange(reflogEntry.Committer.When, before, now);

                Assert.Equal(commit.Id, reflogEntry.To);
                Assert.Equal(ObjectId.Zero, reflogEntry.From);
                Assert.Equal(string.Format("commit (initial): {0}", shortMessage), reflogEntry.Message);

                // Assert a reflog entry is created on HEAD target
                var targetCanonicalName = repo.Refs.Head.TargetIdentifier;
                Assert.Equal(1, repo.Refs.Log(targetCanonicalName).Count());
                Assert.Equal(commit.Id, repo.Refs.Log(targetCanonicalName).First().To);

                File.WriteAllText(filePath, "nulltoken commits!\n");
                repo.Stage(relativeFilepath);

                var    author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5));
                Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2);

                AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n");
                AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n");

                Assert.Equal(1, commit2.Parents.Count());
                Assert.Equal(commit.Id, commit2.Parents.First().Id);

                // Assert the reflog is shifted
                Assert.Equal(2, repo.Refs.Log("HEAD").Count());
                Assert.Equal(reflogEntry.To, repo.Refs.Log("HEAD").First().From);

                Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit);
                repo.Checkout(firstCommitBranch);

                File.WriteAllText(filePath, "davidfowl commits!\n");

                var author3 = new Signature("David Fowler", "*****@*****.**", author.When.AddSeconds(2));
                repo.Stage(relativeFilepath);

                Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3);

                AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n");
                AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n");

                Assert.Equal(1, commit3.Parents.Count());
                Assert.Equal(commit.Id, commit3.Parents.First().Id);

                AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n");
            }
        }
Example #34
0
 public static Branch GetOrCreateBranch(this Repository repo, string branchName)
 {
     return(repo.Branches[branchName] ?? repo.CreateBranch(branchName));
 }
 public void BranchTo(string branchName, string @as = null)
 {
     _sequenceDiagram.BranchTo(branchName, Repository.Head.FriendlyName, @as);
     Repository.Checkout(Repository.CreateBranch(branchName));
 }
        public Task <SourceRepository> FetchAllFiles(BuildConfig config)
        {
            var result = new SourceRepository();

            string gitFolder = config.BuildFolder + "\\git";

            //// temporary hack...
            //// git-pull does not work
            //if (Directory.Exists(gitFolder)) {
            //    Directory.Delete(gitFolder, true);
            //}

            if (!Directory.Exists(gitFolder))
            {
                Directory.CreateDirectory(gitFolder);


                Console.WriteLine("Cloning repository " + config.SourceUrl);

                CloneOptions clone = new CloneOptions();
                clone.CredentialsProvider = CredentialsHandler;
                Repository.Clone(config.SourceUrl, gitFolder, clone);

                Console.WriteLine("Repository clone successful");
            }

            Console.WriteLine("Fetching remote Repository");
            using (var rep = new Repository(gitFolder))
            {
                FetchOptions options = new FetchOptions();
                options.CredentialsProvider = CredentialsHandler;
                Remote remote = rep.Network.Remotes["origin"];

                //Commands.Fetch(rep,remote.Name,)

                //rep.Fetch(remote.Name, options);
                if (!string.IsNullOrWhiteSpace(config.SourceBranch) && config.SourceBranch != "master")
                {
                    if (rep.Head.FriendlyName != config.SourceBranch)
                    {
                        Branch updatedBranch = rep.Branches[config.SourceBranch];
                        if (updatedBranch == null)
                        {
                            string remoteBranchName = "origin/" + config.SourceBranch;
                            var    remoteBranch     = rep.Branches.FirstOrDefault(x => x.FriendlyName == remoteBranchName);
                            if (remoteBranch == null)
                            {
                                throw new ArgumentException($"Branch {remoteBranch} not found in {string.Join(",", rep.Branches.Select(x => x.FriendlyName))}");
                            }

                            var localBranch = rep.CreateBranch(config.SourceBranch, remoteBranch.Tip);

                            updatedBranch = rep.Branches.Update(localBranch, x => x.TrackedBranch = remoteBranch.CanonicalName);
                        }
                        Commands.Checkout(rep, updatedBranch, new CheckoutOptions {
                            CheckoutModifiers = CheckoutModifiers.Force
                        });
                    }
                }

                var merge = Commands.Pull(rep, new Signature("IISCI", "*****@*****.**", DateTime.Now), new PullOptions()
                {
                    FetchOptions = options,
                    MergeOptions = new MergeOptions()
                    {
                        MergeFileFavor  = MergeFileFavor.Theirs,
                        CommitOnSuccess = true
                    }
                });

                Console.WriteLine("Fetch successful");

                result.LatestVersion = Convert.ToBase64String(rep.Head.Tip.Id.RawId);
            }


            List <ISourceItem> files = result.Files;

            EnumerateFiles(new DirectoryInfo(gitFolder), files, "");


            //var md5 = System.Security.Cryptography.MD5.Create();

            Parallel.ForEach(files, file =>
            {
                ((GitSourceItem)file).Version = HashService.Instance.ComputeHash(file.Url);
            });



            return(Task.FromResult(result));
        }
Example #37
0
        public static bool Run(CompressimagesParameters parameters, ICollector <CompressImagesMessage> compressImagesMessages, ILogger logger)
        {
            CredentialsHandler credentialsProvider =
                (url, user, cred) =>
                new UsernamePasswordCredentials {
                Username = KnownGitHubs.Username, Password = parameters.Password
            };

            // clone
            var cloneOptions = new CloneOptions
            {
                CredentialsProvider = credentialsProvider,
            };

            Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions);

            var repo           = new Repository(parameters.LocalPath);
            var remote         = repo.Network.Remotes["origin"];
            var isWikiCompress = parameters.CloneUrl.EndsWith(".wiki.git");

            // check if we have the branch already or this is empty repo
            try
            {
                if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false)
                {
                    logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                    return(false);
                }

                if (!parameters.IsRebase && repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}"))
                {
                    logger.LogInformation("CompressImagesFunction: branch already exists for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                    return(false);
                }
            }
            catch (Exception e)
            {
                // log + ignore
                logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
            }

            // check if we should switch away from the default branch
            if (!isWikiCompress && parameters.Settings != null && !string.IsNullOrEmpty(parameters.Settings.DefaultBranchOverride))
            {
                logger.LogInformation(
                    "CompressImagesFunction: default branch override for {Owner}/{RepoName} is {DefaultBranchOverride}",
                    parameters.RepoOwner,
                    parameters.RepoName,
                    parameters.Settings.DefaultBranchOverride);

                var baseBranch = repo.Branches[$"refs/remotes/origin/{parameters.Settings.DefaultBranchOverride}"];
                if (baseBranch == null)
                {
                    logger.LogWarning(
                        "CompressImagesFunction: default branch ({DefaultBranchOverride}) not found for {Owner}/{RepoName}",
                        parameters.Settings.DefaultBranchOverride,
                        parameters.RepoOwner,
                        parameters.RepoName);
                    return(false);
                }

                Commands.Checkout(repo, baseBranch);
            }

            var repoConfiguration = new RepoConfiguration();

            try
            {
                // see if .imgbotconfig exists in repo root
                var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig");
                if (!string.IsNullOrEmpty(repoConfigJson))
                {
                    repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson);
                }
            }
            catch
            {
                // ignore
            }

            // Add new compressMessage if we should compress Wiki
            if (repoConfiguration.CompressWiki && isWikiCompress == false)
            {
                logger.LogInformation("CompressImagesFunction: Adding Wiki image compression to queue for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                compressImagesMessages.Add(new CompressImagesMessage()
                {
                    InstallationId = parameters.CompressImagesMessage.InstallationId,
                    RepoName       = parameters.CompressImagesMessage.RepoName,
                    Owner          = parameters.RepoOwner,
                    CloneUrl       = $"https://github.com/{parameters.RepoOwner}/{parameters.RepoName}.wiki.git"
                });
            }

            if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false)
            {
                logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName);
                return(false);
            }

            // Should not create branch if we are compressing Wiki or performing rebase
            if (isWikiCompress == false && !parameters.IsRebase)
            {
                // check out the branch
                repo.CreateBranch(KnownGitHubs.BranchName);
                var branch = Commands.Checkout(repo, KnownGitHubs.BranchName);
            }

            // reset any mean files
            repo.Reset(ResetMode.Mixed, repo.Head.Tip);

            // optimize images
            string[]      imagePaths;
            List <string> addedOrModifiedImagePaths = new List <string>();
            List <string> deletedImagePaths         = new List <string>();

            if (parameters.IsRebase)
            {
                var refspec = string.Format("{0}:{0}", KnownGitHubs.BranchName);
                Commands.Fetch(repo, "origin", new List <string> {
                    refspec
                }, null, "fetch");

                var diff = repo.Diff.Compare <TreeChanges>(repo.Branches[KnownGitHubs.BranchName].Commits.ElementAt(1).Tree, repo.Head.Tip.Tree);

                if (diff == null)
                {
                    logger.LogInformation("Something went wrong while doing rebase");
                    return(false);
                }

                foreach (TreeEntryChanges c in diff)
                {
                    if (KnownImgPatterns.ImgExtensions.Contains(Path.GetExtension(c.Path)))
                    {
                        var path    = parameters.LocalPath + "/" + c.Path;
                        var oldpath = parameters.LocalPath + "/" + c.OldPath;

                        switch (c.Status)
                        {
                        case ChangeKind.Added:
                        case ChangeKind.Modified:
                            addedOrModifiedImagePaths.Add(path.Replace("\\", "/"));
                            break;

                        case ChangeKind.Renamed:
                            addedOrModifiedImagePaths.Add(path.Replace("\\", "/"));
                            deletedImagePaths.Add(oldpath.Replace("\\", "/"));
                            break;

                        case ChangeKind.Deleted:
                            deletedImagePaths.Add(path.Replace("\\", "/"));
                            break;
                        }
                    }
                }

                imagePaths = ImageQuery.FilterOutIgnoredFiles(addedOrModifiedImagePaths, repoConfiguration);
            }
            else
            {
                imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration);
            }

            var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression);

            if (optimizedImages.Length == 0)
            {
                return(false);
            }

            // create commit message based on optimizations
            foreach (var image in optimizedImages)
            {
                Commands.Stage(repo, image.OriginalPath);
            }

            var commitMessage = CommitMessage.Create(optimizedImages);
            var signature     = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now);

            repo.Commit(commitMessage, signature, signature);

            if (parameters.IsRebase)
            {
                var baseBranch = repo.Head;
                var newCommit  = baseBranch.Tip;
                var oldCommit  = repo.Branches[KnownGitHubs.BranchName].Tip;

                // we need to reset the default branch so that we can
                // rebase to it later.
                repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1));

                // checkout to imgbot branch. TODO: remove because this is needed earlier on diff
                Commands.Checkout(repo, KnownGitHubs.BranchName);

                // cherry-pick
                var cherryPickOptions = new CherryPickOptions()
                {
                    MergeFileFavor = MergeFileFavor.Theirs,
                };
                var cherryPickResult = repo.CherryPick(newCommit, signature, cherryPickOptions);

                if (cherryPickResult.Status == CherryPickStatus.Conflicts)
                {
                    var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions()
                    {
                    });
                    foreach (var item in status)
                    {
                        if (item.State == FileStatus.Conflicted)
                        {
                            Commands.Stage(repo, item.FilePath);
                        }
                    }

                    repo.Commit(commitMessage, signature, signature);
                }

                // New commit message creation
                var previousCommitResults = CompressionResult.ParseCommitMessage(oldCommit.Message);
                var mergedResults         = CompressionResult.Merge(optimizedImages, previousCommitResults);
                var filteredResults       = CompressionResult.Filter(mergedResults, deletedImagePaths.ToArray());
                var squashCommitMessage   = CommitMessage.Create(filteredResults);

                // squash
                var baseCommit = repo.Head.Commits.ElementAt(2);
                repo.Reset(ResetMode.Soft, baseCommit);
                repo.Commit(squashCommitMessage, signature, signature);

                // rebase
                var rebaseOptions = new RebaseOptions()
                {
                    FileConflictStrategy = CheckoutFileConflictStrategy.Theirs,
                };

                var rebaseResult = repo.Rebase.Start(repo.Head, baseBranch, null, new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions);

                while (rebaseResult.Status == RebaseStatus.Conflicts)
                {
                    var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions()
                    {
                    });
                    foreach (var item in status)
                    {
                        if (item.State == FileStatus.Conflicted)
                        {
                            if (imagePaths.Contains(parameters.LocalPath + "/" + item.FilePath))
                            {
                                Commands.Stage(repo, item.FilePath);
                            }
                            else
                            {
                                Commands.Remove(repo, item.FilePath);
                            }
                        }
                    }

                    rebaseResult = repo.Rebase.Continue(new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions);
                }
            }

            // We just made a normal commit, now we are going to capture all the values generated from that commit
            // then rewind and make a signed commit
            var commitBuffer = Commit.CreateBuffer(
                repo.Head.Tip.Author,
                repo.Head.Tip.Committer,
                repo.Head.Tip.Message,
                repo.Head.Tip.Tree,
                repo.Head.Tip.Parents,
                true,
                null);

            var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword);

            repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha);
            var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData);

            repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep);

            // Should use "master" if we are compressing Wiki
            if (isWikiCompress)
            {
                var branchAgain = Commands.Checkout(repo, "master");
            }
            else
            {
                var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName);
            }

            repo.Reset(ResetMode.Hard, commitToKeep.Sha);

            // verify images are not corrupted by reading from git
            // see https://github.com/dabutvin/ImgBot/issues/273
            try
            {
                foreach (var image in optimizedImages)
                {
                    if (image.OriginalPath.EndsWith(".svg"))
                    {
                        // do not use ImageMagick to verify SVGs
                        continue;
                    }

                    new MagickImage(image.OriginalPath).Dispose();
                }
            }
            catch (MagickErrorException)
            {
                logger.LogError("Corrupt images after reset!");
                return(false);
            }

            // push to GitHub
            if (isWikiCompress)
            {
                repo.Network.Push(remote, "refs/heads/master", new PushOptions
                {
                    CredentialsProvider = credentialsProvider,
                });
            }
            else
            {
                var refs = $"refs/heads/{KnownGitHubs.BranchName}";
                if (parameters.IsRebase)
                {
                    refs = refs.Insert(0, "+");
                }
                logger.LogInformation("refs: {refs}", refs);

                repo.Network.Push(remote, refs, new PushOptions
                {
                    CredentialsProvider = credentialsProvider,
                });
            }

            return(true);
        }
        private static void FeedTheRepository(Repository repo)
        {
            string fullPath = Path.Combine(repo.Info.WorkingDirectory, "a.txt");
            File.WriteAllText(fullPath, "Hello\n");
            repo.Index.Stage(fullPath);
            repo.Commit("Initial commit", Constants.Signature, Constants.Signature);
            repo.ApplyTag("mytag");

            File.AppendAllText(fullPath, "World\n");
            repo.Index.Stage(fullPath);

            Signature shiftedSignature = Constants.Signature.TimeShift(TimeSpan.FromMinutes(1));
            repo.Commit("Update file", shiftedSignature, shiftedSignature);
            repo.CreateBranch("mybranch");

            repo.Checkout("mybranch");

            Assert.False(repo.Index.RetrieveStatus().IsDirty);
        }
Example #39
0
        public void CanFollowBranches(string specificRepoPath)
        {
            var repoPath = specificRepoPath ?? CreateEmptyRepository();
            var path     = "Test.txt";

            var dummy = new string('a', 1024);

            using (var repo = new Repository(repoPath))
            {
                var master0 = AddCommitToOdb(repo, "0. Initial commit for this test", path, "Before merge", dummy);
                var fix1    = AddCommitToOdb(repo, "1. Changed on fix", path, "Change on fix branch", dummy, master0);
                var master2 = AddCommitToOdb(repo, "2. Changed on master", path, "Independent change on master branch",
                                             dummy, master0);

                path = "New" + path;

                var fix3 = AddCommitToOdb(repo, "3. Changed and renamed on fix", path, "Another change on fix branch",
                                          dummy, fix1);
                var master4 = AddCommitToOdb(repo, "4. Changed and renamed on master", path,
                                             "Another independent change on master branch", dummy, master2);
                var master5 = AddCommitToOdb(repo, "5. Merged fix into master", path,
                                             "Manual resolution of merge conflict", dummy, master4, fix3);
                var master6  = AddCommitToOdb(repo, "6. Changed on master", path, "Change after merge", dummy, master5);
                var nextfix7 = AddCommitToOdb(repo, "7. Changed on next-fix", path, "Change on next-fix branch", dummy,
                                              master6);
                var master8 = AddCommitToOdb(repo, "8. Changed on master", path,
                                             "Some arbitrary change on master branch", dummy, master6);
                var master9 = AddCommitToOdb(repo, "9. Merged next-fix into master", path,
                                             "Another manual resolution of merge conflict", dummy, master8, nextfix7);
                var master10 = AddCommitToOdb(repo, "10. Changed on master", path, "A change on master after merging",
                                              dummy, master9);

                repo.CreateBranch("master", master10);
                Commands.Checkout(repo, "master", new CheckoutOptions {
                    CheckoutModifiers = CheckoutModifiers.Force
                });

                // Test --date-order.
                var timeHistory = repo.Commits.QueryBy(path,
                                                       new CommitFilter {
                    SortBy = CommitSortStrategies.Time
                });
                var timeCommits = new List <Commit>
                {
                    master10, // master

                    master8,  // master
                    nextfix7, // next-fix
                    master6,  // master

                    master4,  // master
                    fix3,     // fix
                    master2,  // master
                    fix1,     // fix
                    master0   // master (initial commit)
                };
                Assert.Equal(timeCommits, timeHistory.Select(e => e.Commit));

                // Test --topo-order.
                var topoHistory = repo.Commits.QueryBy(path,
                                                       new CommitFilter {
                    SortBy = CommitSortStrategies.Topological
                });
                var topoCommits = new List <Commit>
                {
                    master10, // master

                    nextfix7, // next-fix
                    master8,  // master
                    master6,  // master

                    fix3,     // fix
                    fix1,     // fix
                    master4,  // master
                    master2,  // master
                    master0   // master (initial commit)
                };
                Assert.Equal(topoCommits, topoHistory.Select(e => e.Commit));
            }
        }
Example #40
0
        public void CheckingOutWithMergeConflictsThrows()
        {
            string repoPath = InitNewRepository();

            using (var repo = new Repository(repoPath))
            {
                Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello\n");
                repo.Stage(originalFilePath);
                repo.Commit("Initial commit", Constants.Signature, Constants.Signature);

                // Create 2nd branch
                repo.CreateBranch("branch2");

                // Update file in main
                Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello from master!\n");
                repo.Stage(originalFilePath);
                repo.Commit("2nd commit", Constants.Signature, Constants.Signature);

                // Checkout branch2
                repo.Checkout("branch2");
                Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello From branch2!\n");

                // Assert that checking out master throws
                // when there are unstaged commits
                Assert.Throws<MergeConflictException>(() => repo.Checkout("master"));

                // And when there are staged commits
                repo.Stage(originalFilePath);
                Assert.Throws<MergeConflictException>(() => repo.Checkout("master"));
            }
        }
Example #41
0
        public static bool Run(CompressimagesParameters parameters)
        {
            CredentialsHandler credentialsProvider =
                (url, user, cred) =>
                new UsernamePasswordCredentials {
                Username = KnownGitHubs.Username, Password = parameters.Password
            };

            // clone
            var cloneOptions = new CloneOptions
            {
                CredentialsProvider = credentialsProvider,
            };

            Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions);

            var repo   = new Repository(parameters.LocalPath);
            var remote = repo.Network.Remotes["origin"];

            // check if we have the branch already or this is empty repo
            try
            {
                if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false)
                {
                    return(false);
                }

                if (repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}"))
                {
                    return(false);
                }
            }
            catch
            {
                // ignore
            }

            var repoConfiguration = new RepoConfiguration();

            try
            {
                // see if .imgbotconfig exists in repo root
                var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig");
                if (!string.IsNullOrEmpty(repoConfigJson))
                {
                    repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson);
                }
            }
            catch
            {
                // ignore
            }

            if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false)
            {
                return(false);
            }

            // check out the branch
            repo.CreateBranch(KnownGitHubs.BranchName);
            var branch = Commands.Checkout(repo, KnownGitHubs.BranchName);

            // reset any mean files
            repo.Reset(ResetMode.Mixed, repo.Head.Tip);

            // optimize images
            var imagePaths      = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration);
            var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths);

            if (optimizedImages.Length == 0)
            {
                return(false);
            }

            // create commit message based on optimizations
            var commitMessage = CommitMessage.Create(optimizedImages);

            // commit
            var signature = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now);

            repo.Commit(commitMessage, signature, signature);

            // We just made a normal commit, now we are going to capture all the values generated from that commit
            // then rewind and make a signed commit
            var commitBuffer = Commit.CreateBuffer(
                repo.Head.Tip.Author,
                repo.Head.Tip.Committer,
                repo.Head.Tip.Message,
                repo.Head.Tip.Tree,
                repo.Head.Tip.Parents,
                true,
                null);

            var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKeyStream, parameters.PgPPassword);

            repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha);
            var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData);

            repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep);
            var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName);

            repo.Reset(ResetMode.Hard, commitToKeep.Sha);

            // push to GitHub
            repo.Network.Push(remote, $"refs/heads/{KnownGitHubs.BranchName}", new PushOptions
            {
                CredentialsProvider = credentialsProvider,
            });

            return(true);
        }
Example #42
0
        private IGitTfsRemote InitTfsBranch(RemoteOptions remoteOptions, string tfsRepositoryPath, int rootChangesetId = -1, bool fetchParentBranch = false, string gitBranchNameExpected = null, IRenameResult renameResult = null)
        {
            Trace.WriteLine("Begin process of creating branch for remote :" + tfsRepositoryPath);
            // TFS string representations of repository paths do not end in trailing slashes
            tfsRepositoryPath = (tfsRepositoryPath ?? string.Empty).TrimEnd('/');

            string gitBranchName = ExtractGitBranchNameFromTfsRepositoryPath(
                string.IsNullOrWhiteSpace(gitBranchNameExpected) ? tfsRepositoryPath : gitBranchNameExpected);

            if (string.IsNullOrWhiteSpace(gitBranchName))
            {
                throw new GitTfsException("error: The Git branch name '" + gitBranchName + "' is not valid...\n");
            }
            Trace.WriteLine("Git local branch will be :" + gitBranchName);

            string sha1RootCommit = null;

            if (rootChangesetId != -1)
            {
                sha1RootCommit = Repository.FindCommitHashByChangesetId(rootChangesetId);
                if (fetchParentBranch && string.IsNullOrWhiteSpace(sha1RootCommit))
                {
                    sha1RootCommit = FindRootRemoteAndFetch(rootChangesetId, renameResult);
                }
                if (string.IsNullOrWhiteSpace(sha1RootCommit))
                {
                    return(null);
                }

                Trace.WriteLine("Found commit " + sha1RootCommit + " for changeset :" + rootChangesetId);
            }

            IGitTfsRemote tfsRemote;

            if (Repository.HasRemote(gitBranchName))
            {
                Trace.WriteLine("Remote already exist");
                tfsRemote = Repository.ReadTfsRemote(gitBranchName);
                if (tfsRemote.TfsUrl != TfsUrl)
                {
                    Trace.WriteLine("warning: Url is different");
                }
                if (tfsRemote.TfsRepositoryPath != tfsRepositoryPath)
                {
                    Trace.WriteLine("warning: TFS repository path is different");
                }
            }
            else
            {
                Trace.WriteLine("Try creating remote...");
                tfsRemote = Repository.CreateTfsRemote(new RemoteInfo
                {
                    Id            = gitBranchName,
                    Url           = TfsUrl,
                    Repository    = tfsRepositoryPath,
                    RemoteOptions = remoteOptions
                }, string.Empty);
            }
            if (sha1RootCommit != null && !Repository.HasRef(tfsRemote.RemoteRef))
            {
                if (!Repository.CreateBranch(tfsRemote.RemoteRef, sha1RootCommit))
                {
                    throw new GitTfsException("error: Fail to create remote branch ref file!");
                }
            }
            Trace.WriteLine("Remote created!");
            return(tfsRemote);
        }
Example #43
0
 Branch CreateBranch(string name, CommitNodeModel n)
 {
     return(Repository.CreateBranch(name, n.Commit));
 }
Example #44
0
        public void CanMergeRepoNonFastForward(bool shouldMergeOccurInDetachedHeadState)
        {
            const string firstBranchFileName = "first branch file.txt";
            const string secondBranchFileName = "second branch file.txt";
            const string sharedBranchFileName = "first+second branch file.txt";

            string path = CloneStandardTestRepo();

            using (var repo = new Repository(path))
            {
                var firstBranch = repo.CreateBranch("FirstBranch");
                firstBranch.Checkout();
                var originalTreeCount = firstBranch.Tip.Tree.Count;

                // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit).
                AddFileCommitToRepo(repo, sharedBranchFileName);

                var secondBranch = repo.CreateBranch("SecondBranch");
                // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one).
                AddFileCommitToRepo(repo, firstBranchFileName);

                if (shouldMergeOccurInDetachedHeadState)
                {
                    // Detaches HEAD
                    repo.Checkout(secondBranch.Tip);
                }
                else
                {
                    secondBranch.Checkout();
                }

                // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit).
                AddFileCommitToRepo(repo, secondBranchFileName);

                MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature);

                Assert.Equal(MergeStatus.NonFastForward, mergeResult.Status);

                Assert.Equal(repo.Head.Tip, mergeResult.Commit);
                Assert.Equal(originalTreeCount + 3, mergeResult.Commit.Tree.Count);    // Expecting original tree count plussed by the 3 added files.
                Assert.Equal(2, mergeResult.Commit.Parents.Count());   // Merge commit should have 2 parents
                Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached);

                if (!shouldMergeOccurInDetachedHeadState)
                {
                    // Ensure HEAD is still attached and points to SecondBranch
                    Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName);
                }
            }
        }
Example #45
0
        public void Checkout(string refspec = "master", CancellationToken token = default(CancellationToken))
        {
            var checkoutOptions = new CheckoutOptions {
                CheckoutModifiers = CheckoutModifiers.Force,
            };

            // Clone repository if it does not exist
            if (!Repository.IsValid(Source.RepositoryPath))
            {
                Output.WriteLine("Cloning Repository...", ConsoleColor.DarkCyan);

                var cloneOptions = new CloneOptions();
                cloneOptions.CredentialsProvider += CredentialsProvider;

                Repository.Clone(Source.RepositoryUrl, Source.RepositoryPath, cloneOptions);
            }

            using (var repo = new Repository(Source.RepositoryPath)) {
                // Fetch all updated refspecs and tags
                Output.WriteLine("Fetching updated refs...", ConsoleColor.DarkCyan);

                var fetchSpec    = new[] { "+refs/heads/*:refs/remotes/origin/*" };
                var fetchOptions = new FetchOptions {
                    TagFetchMode = TagFetchMode.All,
                };

                fetchOptions.CredentialsProvider += CredentialsProvider;

                LibGit2Sharp.Commands.Fetch(repo, "origin", fetchSpec, fetchOptions, null);

                // Find local and remote branches
                var remoteBranchName = $"refs/remotes/origin/{refspec}";
                var remoteBranch     = repo.Branches[remoteBranchName];

                var localBranchName = $"refs/heads/origin/{refspec}";
                var localBranch     = repo.Branches[localBranchName];

                if (remoteBranch == null)
                {
                    Output.Write("Git Refspec ", ConsoleColor.DarkYellow)
                    .Write(refspec, ConsoleColor.Yellow)
                    .WriteLine(" was not found!", ConsoleColor.DarkYellow);

                    throw new ApplicationException($"Git Refspec '{refspec}' was not found!");
                }

                if (localBranch != null)
                {
                    Output.WriteLine($"Found local branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan);

                    // Update tracking branch if not remote branch
                    if (!localBranch.IsTracking || localBranch.TrackedBranch != remoteBranch)
                    {
                        Output.WriteLine("Updating local branch tracking reference...", ConsoleColor.DarkCyan);

                        repo.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName);
                    }

                    // Checkout local branch if not current
                    if (!localBranch.IsCurrentRepositoryHead)
                    {
                        Output.WriteLine($"Checkout local branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan);

                        LibGit2Sharp.Commands.Checkout(repo, localBranch, checkoutOptions);
                    }

                    // Revert to common ancestor commit if diverged
                    var status     = localBranch.TrackingDetails;
                    var aheadCount = status.AheadBy ?? 0;

                    if (aheadCount > 0)
                    {
                        Output.WriteLine($"Local branch '{localBranch.FriendlyName}' has diverged from the remote tracking branch!", ConsoleColor.DarkYellow);

                        var common = status.CommonAncestor;

                        if (common != null)
                        {
                            Output.WriteLine($"Reverting local branch to commit '{common.Sha}'!", ConsoleColor.DarkCyan);

                            repo.Reset(ResetMode.Hard, common, checkoutOptions);
                        }
                    }

                    // Pull latest changes from remote
                    Output.WriteLine("Pull changes from remote...", ConsoleColor.DarkCyan);

                    var sign = new Signature("photon", "*****@*****.**", DateTimeOffset.Now);

                    var pullOptions = new PullOptions {
                        FetchOptions = fetchOptions,
                    };

                    LibGit2Sharp.Commands.Pull(repo, sign, pullOptions);
                }
                else
                {
                    // Create local branch tracking remote
                    Output.WriteLine($"No local branch found. Creating local tracking branch '{remoteBranch.FriendlyName}'...", ConsoleColor.DarkCyan);
                    localBranch = repo.CreateBranch(remoteBranch.FriendlyName, remoteBranch.Tip);
                    repo.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName);

                    Output.WriteLine($"Checkout local tracking branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan);

                    LibGit2Sharp.Commands.Checkout(repo, localBranch, checkoutOptions);
                }

                var commit = repo.Head?.Tip;
                CommitHash    = commit?.Sha;
                CommitAuthor  = commit?.Author?.Name;
                CommitMessage = commit?.Message;

                Output.WriteLine("Current Commit:", ConsoleColor.DarkBlue)
                .WriteLine($"  {CommitHash}", ConsoleColor.Blue)
                .WriteLine($"  {CommitAuthor}", ConsoleColor.Blue)
                .WriteLine(CommitMessage, ConsoleColor.Cyan);
            }
        }
Example #46
0
        public void IsUpToDateMerge()
        {
            const string sharedBranchFileName = "first+second branch file.txt";

            string path = CloneStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var firstBranch = repo.CreateBranch("FirstBranch");
                firstBranch.Checkout();

                // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit).
                AddFileCommitToRepo(repo, sharedBranchFileName);

                var secondBranch = repo.CreateBranch("SecondBranch");

                secondBranch.Checkout();

                MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature);

                Assert.Equal(MergeStatus.UpToDate, mergeResult.Status);
            }
        }
Example #47
0
        public void CreatingABranchTriggersTheCreationOfADirectReference()
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
            using (var repo = new Repository(path.RepositoryPath))
            {
                Branch newBranch = repo.CreateBranch("clone-of-master");
                Assert.False(newBranch.IsCurrentRepositoryHead);

                ObjectId commitId = repo.Head.Tip.Id;
                Assert.Equal(commitId, newBranch.Tip.Id);

                Reference reference = repo.Refs[newBranch.CanonicalName];
                Assert.NotNull(reference);
                Assert.IsType(typeof(DirectReference), reference);
            }
        }
Example #48
0
        public void CanCreateBranch(string name)
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
            using (var repo = new Repository(path.RepositoryPath))
            {
                Branch newBranch = repo.CreateBranch(name, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
                Assert.NotNull(newBranch);
                Assert.Equal(name, newBranch.Name);
                Assert.Equal("refs/heads/" + name, newBranch.CanonicalName);
                Assert.NotNull(newBranch.Tip);
                Assert.Equal("be3563ae3f795b2b4353bcce3a527ad0a4f7f644", newBranch.Tip.Sha);
                Assert.NotNull(repo.Branches.SingleOrDefault(p => p.Name == name));

                repo.Branches.Delete(newBranch.Name);
            }
        }
Example #49
0
 public void CanCreateBranchUsingAbbreviatedSha()
 {
     TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
     using (var repo = new Repository(path.RepositoryPath))
     {
         const string name = "unit_test";
         Branch newBranch = repo.CreateBranch(name, "be3563a");
         Assert.Equal("refs/heads/" + name, newBranch.CanonicalName);
         Assert.Equal("be3563ae3f795b2b4353bcce3a527ad0a4f7f644", newBranch.Tip.Sha);
     }
 }
Example #50
0
 Branch CreateBranch(string name, BranchLabelModel l)
 {
     return(Repository.CreateBranch(name, l.Branch.Tip));
 }
Example #51
0
        public static async Task <ConfigurationState <RunnerRepoInfo> > CheckoutRunnerRepository(
            string proj,
            string localRepoDir,
            GitPatcherVersioning patcherVersioning,
            NugetVersioningTarget nugetVersioning,
            Action <string>?logger,
            CancellationToken cancel,
            bool compile = true)
        {
            try
            {
                cancel.ThrowIfCancellationRequested();

                logger?.Invoke($"Targeting {patcherVersioning}");

                using var repo = new Repository(localRepoDir);
                var runnerBranch = repo.Branches[RunnerBranch] ?? repo.CreateBranch(RunnerBranch);
                repo.Reset(ResetMode.Hard);
                Commands.Checkout(repo, runnerBranch);
                string?targetSha;
                string?target;
                bool   fetchIfMissing = patcherVersioning.Versioning switch
                {
                    PatcherVersioningEnum.Commit => true,
                    _ => false
                };
                switch (patcherVersioning.Versioning)
                {
                case PatcherVersioningEnum.Tag:
                    if (string.IsNullOrWhiteSpace(patcherVersioning.Target))
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail("No tag selected"));
                    }
                    repo.Fetch();
                    targetSha = repo.Tags[patcherVersioning.Target]?.Target.Sha;
                    if (string.IsNullOrWhiteSpace(targetSha))
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail("Could not locate tag"));
                    }
                    target = patcherVersioning.Target;
                    break;

                case PatcherVersioningEnum.Commit:
                    targetSha = patcherVersioning.Target;
                    if (string.IsNullOrWhiteSpace(targetSha))
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit"));
                    }
                    target = patcherVersioning.Target;
                    break;

                case PatcherVersioningEnum.Branch:
                    if (string.IsNullOrWhiteSpace(patcherVersioning.Target))
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail($"Target branch had no name."));
                    }
                    repo.Fetch();
                    var targetBranch = repo.Branches[$"origin/{patcherVersioning.Target}"];
                    if (targetBranch == null)
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail($"Could not locate branch: {patcherVersioning.Target}"));
                    }
                    targetSha = targetBranch.Tip.Sha;
                    target    = patcherVersioning.Target;
                    break;

                default:
                    throw new NotImplementedException();
                }
                if (!ObjectId.TryParse(targetSha, out var objId))
                {
                    return(GetResponse <RunnerRepoInfo> .Fail("Malformed sha string"));
                }

                cancel.ThrowIfCancellationRequested();
                var commit = repo.Lookup(objId, ObjectType.Commit) as Commit;
                if (commit == null)
                {
                    if (!fetchIfMissing)
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit with given sha"));
                    }
                    repo.Fetch();
                    commit = repo.Lookup(objId, ObjectType.Commit) as Commit;
                    if (commit == null)
                    {
                        return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit with given sha"));
                    }
                }

                cancel.ThrowIfCancellationRequested();
                var slnPath = GitPatcherRun.GetPathToSolution(localRepoDir);
                if (slnPath == null)
                {
                    return(GetResponse <RunnerRepoInfo> .Fail("Could not locate solution to run."));
                }

                var foundProjSubPath = SolutionPatcherRun.AvailableProject(slnPath, proj);

                if (foundProjSubPath == null)
                {
                    return(GetResponse <RunnerRepoInfo> .Fail($"Could not locate target project file: {proj}."));
                }

                cancel.ThrowIfCancellationRequested();
                logger?.Invoke($"Checking out {targetSha}");
                repo.Reset(ResetMode.Hard, commit, new CheckoutOptions());

                var projPath = Path.Combine(localRepoDir, foundProjSubPath);

                cancel.ThrowIfCancellationRequested();
                logger?.Invoke($"Mutagen Nuget: {nugetVersioning.MutagenVersioning} {nugetVersioning.MutagenVersion}");
                logger?.Invoke($"Synthesis Nuget: {nugetVersioning.SynthesisVersioning} {nugetVersioning.SynthesisVersion}");
                GitPatcherRun.SwapInDesiredVersionsForSolution(
                    slnPath,
                    drivingProjSubPath: foundProjSubPath,
                    mutagenVersion: nugetVersioning.MutagenVersioning == NugetVersioningEnum.Match ? null : nugetVersioning.MutagenVersion,
                    listedMutagenVersion: out var listedMutagenVersion,
                    synthesisVersion: nugetVersioning.SynthesisVersioning == NugetVersioningEnum.Match ? null : nugetVersioning.SynthesisVersion,
                    listedSynthesisVersion: out var listedSynthesisVersion);

                // Compile to help prep
                if (compile)
                {
                    var compileResp = await SolutionPatcherRun.CompileWithDotnet(projPath, cancel);

                    if (compileResp.Failed)
                    {
                        return(compileResp.BubbleFailure <RunnerRepoInfo>());
                    }
                }

                return(GetResponse <RunnerRepoInfo> .Succeed(
                           new RunnerRepoInfo(
                               slnPath : slnPath,
                               projPath : projPath,
                               target : target,
                               commitMsg : commit.Message,
                               commitDate : commit.Author.When.LocalDateTime,
                               listedSynthesis : listedSynthesisVersion,
                               listedMutagen : listedMutagenVersion)));
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                return(GetResponse <RunnerRepoInfo> .Fail(ex));
            }
        }
Example #52
0
 public void CanCreateBranchFromCommit()
 {
     TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
     using (var repo = new Repository(path.RepositoryPath))
     {
         const string name = "unit_test";
         var commit = repo.Lookup<Commit>("HEAD");
         Branch newBranch = repo.CreateBranch(name, commit);
         Assert.NotNull(newBranch);
         Assert.Equal("4c062a6361ae6959e06292c1fa5e2822d9c96345", newBranch.Tip.Sha);
     }
 }
Example #53
0
        public static async void createPR(String stack)
        {
            String _gitToken = File.ReadAllText("../../../gitToken.txt");
            // clone master
            String timeStamp   = DateTime.Now.ToString("yyyyMMddHHmmss");
            String root        = String.Format("D:\\local\\temp\\blimpPR{0}", timeStamp);
            String upstream    = root + "\\" + stack;
            String upstreamURL = String.Format("https://github.com/Azure-App-Service/{0}.git", stack);
            String branch      = String.Format("blimp{0}", timeStamp);

            Repository.Clone(upstreamURL, upstream, new CloneOptions {
                BranchName = "dev"
            });

            // branch
            Repository repo = new Repository(upstream);

            repo.CreateBranch(branch);
            Commands.Checkout(repo, branch);

            // list temp repos
            HttpClient httpClient = new HttpClient();

            httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("patricklee2");
            HttpResponseMessage response   = null;
            List <Repo>         resultList = new List <Repo>();
            List <Repo>         stackRepos = null;
            int run = 0;

            while (true)
            {
                String generatedReposURL = String.Format("https://api.github.com/orgs/{0}/repos?page={1}&per_page=30&sort=full_name&direction=asc", "blessedimagepipeline", run);
                response = await httpClient.GetAsync(generatedReposURL);

                response.EnsureSuccessStatusCode();
                string contentString = await response.Content.ReadAsStringAsync();

                List <Repo> l = JsonConvert.DeserializeObject <List <Repo> >(contentString);
                resultList.AddRange(l);
                run++;
                if (l.Count < 30)
                {
                    break;
                }
            }
            switch (stack)
            {
            case "dotnetcore":
                stackRepos = resultList.FindAll(isDotnetcoreRepo);
                break;

            case "node":
                stackRepos = resultList.FindAll(isNodeRepo);
                break;

            case "php":
                stackRepos = resultList.FindAll(isPhpRepo);
                break;

            case "python":
                stackRepos = resultList.FindAll(isPythonRepo);
                break;

            case "ruby":
                stackRepos = resultList.FindAll(isRubyRepo);
                rubyBase(resultList.FindAll(isRubyBaseRepo), root, upstream);
                break;
            }
            // List<Repo> stackRepos = resultList.FindAll(isStackRepo(stack));

            foreach (Repo r in stackRepos)
            {
                try
                {
                    Console.WriteLine("copying " + r.full_name);
                    // pull temps
                    String dest = root + "\\" + r.name;
                    Repository.Clone(r.clone_url, dest, new CloneOptions {
                        BranchName = "dev"
                    });

                    // move
                    String version = r.name.ToLower().Replace(stack + "-", "");
                    String suffix  = "";
                    if (stack.Equals("php"))
                    {
                        suffix = "-apache";
                    }
                    GitHubUtils githubUtils = new GitHubUtils("fake");
                    githubUtils.Delete(upstream + "\\" + version + suffix, skipGit: true);
                    githubUtils.DeepCopy(dest, upstream + "\\" + version + suffix);

                    // stage
                    Commands.Stage(repo, upstream + "\\" + version + suffix);
                }
                catch (LibGit2Sharp.NameConflictException e)
                {
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }


            // git commit
            // Create the committer's signature and commit
            //_log.Info("git commit");
            Signature author    = new Signature("blimp", "*****@*****.**", DateTime.Now);
            Signature committer = author;

            // Commit to the repository
            try
            {
                Commit commit = repo.Commit("blimp", author, committer);
            }
            catch (Exception e)
            {
                //_log.info("Empty commit");
            }

            Remote remote = repo.Network.Remotes.Add("upstream", upstreamURL);

            repo.Branches.Update(repo.Head, b => b.Remote = remote.Name, b => b.UpstreamBranch = repo.Head.CanonicalName);

            // git push
            //_log.Info("git push");
            LibGit2Sharp.PushOptions options = new LibGit2Sharp.PushOptions();
            options.CredentialsProvider = new CredentialsHandler(
                (url, usernameFromUrl, types) =>
                new UsernamePasswordCredentials()
            {
                Username = _gitToken.Trim(),
                Password = String.Empty
            });
            repo.Network.Push(repo.Branches[branch], options); // fails if branch already exists

            //create PR

            String pullRequestURL = String.Format("https://api.github.com/repos/{0}/{1}/pulls?access_token={2}", "azure-app-service", stack, _gitToken);
            String body           =
                "{ " +
                "\"title\": " + JsonConvert.SerializeObject("sync from templates") + ", " +
                "\"body\": " + JsonConvert.SerializeObject("sync from templates") + ", " +
                "\"head\": " + JsonConvert.SerializeObject("azure-app-service:" + branch) + ", " +
                "\"base\": " + JsonConvert.SerializeObject("dev") +

                "}";

            response = await httpClient.PostAsync(pullRequestURL, new StringContent(body)); // fails on empty commits

            String result = await response.Content.ReadAsStringAsync();

            System.Console.WriteLine(response.ToString());
            System.Console.WriteLine(result);
            if (response.StatusCode == HttpStatusCode.UnprocessableEntity)
            {
                System.Console.WriteLine("Unable to make PR due to no differnce");
            }

            //cleanup
            //new DirectoryInfo(root).Delete(true);
        }
Example #54
0
        public void CanLookupABranchWhichNameIsMadeOfNon7BitsAsciiCharacters()
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
            using (var repo = new Repository(path.RepositoryPath))
            {
                const string name = "Ångström";
                Branch newBranch = repo.CreateBranch(name, "be3563a");
                Assert.NotNull(newBranch);

                Branch retrieved = repo.Branches["Ångström"];
                Assert.NotNull(retrieved);
                Assert.Equal(newBranch.Tip, retrieved.Tip);
            }
        }
Example #55
0
    private static FileInfo CommitFileOnBranch(Repository repo, string branchName, String content)
    {
        var branch = repo.CreateBranch(branchName);
            Commands.Checkout(repo, branch.FriendlyName);

            FileInfo expectedPath = StageNewFile(repo, content);
            repo.Commit("Commit", Constants.Signature, Constants.Signature);
            return expectedPath;
    }
Example #56
0
 public void CreatingABranchFromATagPeelsToTheCommit()
 {
     TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
     using (var repo = new Repository(path.RepositoryPath))
     {
         const string name = "i-peel-tag";
         Branch newBranch = repo.CreateBranch(name, "refs/tags/test");
         Assert.NotNull(newBranch);
         Assert.Equal("e90810b8df3e80c413d903f631643c716887138d", newBranch.Tip.Sha);
     }
 }
 public void BranchToFromTag(string branchName, string fromTag, string onBranch, string @as = null)
 {
     _sequenceDiagram.BranchToFromTag(branchName, fromTag, onBranch, @as);
     Repository.Checkout(Repository.CreateBranch(branchName));
 }
Example #58
0
 public void CreatingBranchWithBadParamsThrows()
 {
     using (var repo = new Repository(BareTestRepoPath))
     {
         Assert.Throws<ArgumentNullException>(() => repo.Branches.Create(null, repo.Head.CanonicalName));
         Assert.Throws<ArgumentException>(() => repo.Branches.Create(string.Empty, repo.Head.CanonicalName));
         Assert.Throws<ArgumentNullException>(() => repo.Branches.Create("bad_branch", default(string)));
         Assert.Throws<ArgumentException>(() => repo.Branches.Create("bad_branch", string.Empty));
         Assert.Throws<ArgumentNullException>(() => repo.CreateBranch("bad_branch", default(Commit)));
     }
 }
Example #59
0
        static int Main(string[] args)
        {
            // Get configration settings from the appsettings.json file.
            ConfigureApplication();

            // Validate and cache arguments.
            if (!CheckArguments(args))
            {
                Console.WriteLine(Usage);
                return(ErrorCode);
            }

            // Create a Repository instance on the local path to the git repo.
            using (var repo = new Repository(RepoLocalPath))
            {
                // Fetch the state of the remote repo, which is typically named "upstream".
                PrintMessage($"Fetching state of {RemoteRepoName}");
                var    remote     = repo.Network.Remotes[RemoteRepoName];
                var    refSpecs   = remote.FetchRefSpecs.Select(x => x.Specification);
                string logMessage = "";
                Commands.Fetch(repo, remote.Name, refSpecs, null, logMessage);

                // Get the branch to cherry-pick from.
                var sourceBranch = repo.Branches[SourceBranchName];
                if (sourceBranch == null)
                {
                    // Repository returns a null object when the requested branch doesn't exist.
                    PrintMessage($"Source branch {SourceBranchName} not found in {RemoteRepoName}, exiting.");
                    return(ErrorCode);
                }
                else
                {
                    PrintMessage($"Found branch {sourceBranch.FriendlyName} in {RemoteRepoName}");
                }

                // Find the commit in the git log of the source branch.
                var sourceCommit = sourceBranch.Commits.FirstOrDefault(c => c.Sha == CommitSha);
                if (sourceCommit == null)
                {
                    PrintMessage($"Commit {CommitSha} not found in {sourceBranch.FriendlyName}, no action taken, exiting.");
                    return(ErrorCode);
                }

                // Get the branches to merge to, which is a list of the available
                // branches minus the source branch for the commit.
                var branchesToMerge = AvailableBranches.Where(b => b != SourceBranchName);

                // Assign cherry-pick options.
                CherryPickOptions options = CreateCherryPickOptions();

                // Set up the signature for the cherry-pick message.
                Signature sig = new Signature(SigName, SigEmail, DateTime.Now);

                // Create local branches that track the available remote branches.
                // In each local branch, do the cherry-pick and push to the remote repo.
                PrintMessage($"Cherry-picking from {sourceBranch.FriendlyName} to available branches.");
                foreach (var trackedBranchName in branchesToMerge)
                {
                    // Create and check out the local branch, which is equivalent to the command:
                    //
                    // git checkout -b <local-branch-name> -t <remote-repo-name>/<tracked-branch-name>
                    //
                    // For example, the following command creates a local branch
                    // named "docs-2358" which tracks the remote branch named "0.8.1-ksqldb"
                    // in the remote repo named "upstream":
                    //
                    // git checkout -b docs-2358 -t upstream/0.8.1-ksqldb

                    // Name the local branch by appending the remote branch name to the provided base name.
                    // For example, if the base name is "docs-2358" and the tracked branch is named
                    // "0.8.1-ksqldb", the local branch name is "docs-2358-0.8.1-ksqldb".
                    string localBranchName = $"{LocalBranchBaseName}-{trackedBranchName}";

                    // For future reference, this is the "objectish" representation:
                    // string objectish = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", localBranch.CanonicalName, localBranch.UpstreamBranchCanonicalName);

                    // Get a reference on the remote tracking branch.
                    Branch trackedBranch = repo.Branches[$"{RemoteRepoName}/{trackedBranchName}"];

                    // If a local branch with the same name exists, probably from a
                    // previous MyPintMerge session, delete it.
                    if (repo.Branches.Any(b => b.FriendlyName == localBranchName))
                    {
                        DeleteBranch(repo, repo.Branches[localBranchName]);
                    }

                    // Create and check out the local branch.
                    PrintMessage($"Checking out local branch {localBranchName} tracking remote branch {trackedBranch.FriendlyName}");
                    Branch localBranch   = repo.CreateBranch(localBranchName, trackedBranch.Tip);
                    Branch updatedBranch = repo.Branches.Update(
                        localBranch,
                        b => b.TrackedBranch = trackedBranch.CanonicalName);
                    CheckoutOptions checkoutOptions = CreateCheckoutOptions();
                    checkoutCounter = 0;
                    Commands.Checkout(repo, localBranch, checkoutOptions);

                    // Cherry-pick to the currently checked out branch.
                    PrintMessage($"Cherry-picking commit {sourceCommit.Sha} to local branch {updatedBranch.FriendlyName}");
                    try
                    {
                        var pickResult = repo.CherryPick(sourceCommit, sig, options);

                        // Check the return value from the CherryPick method,
                        // which can fail without throwing or sending a notification
                        // to the callbacks.
                        if (pickResult.Status == CherryPickStatus.Conflicts)
                        {
                            // If there are merge conflcts, exit.
                            PrintMessage($"CONFLICT in local branch {updatedBranch.FriendlyName}, exiting.");
                            return(ErrorCode);
                        }
                    }
                    catch (EmptyCommitException ecex)
                    {
                        // Oddly, when there's nothing to do, i.e., when the commit
                        // exists already in the tracked branch, libgit2sharp
                        // throws an EmptyCommitException instead of reutrning
                        // a CherryPickResult.
                        PrintMessage($"No changes detected, no action taken in local branch {updatedBranch.FriendlyName}, continuing.");

                        if (DeleteLocalBranches)
                        {
                            DeleteBranch(repo, localBranch);
                        }

                        continue;
                    }
                    catch (Exception ex)
                    {
                        PrintMessage($"Exception during cherry-pick {ex}, no action taken in local branch {updatedBranch.FriendlyName}, continuing.");

                        //if (DeleteLocalBranches)
                        //{
                        //    DeleteBranch(repo, localBranch);
                        //}

                        continue;
                    }

                    // Prepare to push the changes to the tracked remote branch.
                    // Assign the configuration options for the push.
                    PushOptions pushOptions = CreatePushOptions();

                    // Push the branch to the remote repo.
                    PrintMessage($"Pushing local branch {localBranchName} to remote {trackedBranch.FriendlyName}");
                    repo.Network.Push(localBranch, pushOptions);

                    // Optionally, clean up by deleting the local branch.
                    if (DeleteLocalBranches)
                    {
                        DeleteBranch(repo, localBranch);
                    }
                }
            }

            return(SuccessCode);
        }