public void CanCreateABlobIntoTheDatabaseOfABareRepository()
        {
            string path = InitNewRepository();

            SelfCleaningDirectory directory = BuildSelfCleaningDirectory();

            string filepath = Touch(directory.RootedDirectoryPath, "hello.txt", "I'm a new file\n");

            using (var repo = new Repository(path))
            {
                /*
                 * $ echo "I'm a new file" | git hash-object --stdin
                 * dc53d4c6b8684c21b0b57db29da4a2afea011565
                 */
                Assert.Null(repo.Lookup<Blob>("dc53d4c6b8684c21b0b57db29da4a2afea011565"));

                Blob blob = repo.ObjectDatabase.CreateBlob(filepath);

                Assert.NotNull(blob);
                Assert.Equal("dc53d4c6b8684c21b0b57db29da4a2afea011565", blob.Sha);
                Assert.Equal("I'm a new file\n", blob.GetContentText());

                var fetchedBlob = repo.Lookup<Blob>(blob.Id);
                Assert.Equal(blob, fetchedBlob);
            }
        }
        public void CanCreateABlobIntoTheDatabaseOfABareRepository()
        {
            TemporaryCloneOfTestRepo scd = BuildTemporaryCloneOfTestRepo();

            SelfCleaningDirectory directory = BuildSelfCleaningDirectory();

            Directory.CreateDirectory(directory.RootedDirectoryPath);
            string filepath = Path.Combine(directory.RootedDirectoryPath, "hello.txt");
            File.WriteAllText(filepath, "I'm a new file\n");

            using (var repo = new Repository(scd.RepositoryPath))
            {
                /*
                 * $ echo "I'm a new file" | git hash-object --stdin
                 * dc53d4c6b8684c21b0b57db29da4a2afea011565
                 */
                Assert.Null(repo.Lookup<Blob>("dc53d4c6b8684c21b0b57db29da4a2afea011565"));

                Blob blob = repo.ObjectDatabase.CreateBlob(filepath);

                Assert.NotNull(blob);
                Assert.Equal("dc53d4c6b8684c21b0b57db29da4a2afea011565", blob.Sha);
                Assert.Equal("I'm a new file\n", blob.ContentAsUtf8());

                var fetchedBlob = repo.Lookup<Blob>(blob.Id);
                Assert.Equal(blob, fetchedBlob);
            }
        }
Example #3
0
        public void CanAddAndRemoveStash()
        {
            string path = SandboxStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var stasher = Constants.Signature;

                Assert.True(repo.RetrieveStatus().IsDirty);

                Stash stash = repo.Stashes.Add(stasher, "My very first stash", StashModifiers.IncludeUntracked);

                // Check that untracked files are deleted from working directory
                string untrackedFilename = "new_untracked_file.txt";
                Assert.False(File.Exists(Path.Combine(repo.Info.WorkingDirectory, untrackedFilename)));
                Assert.NotNull(stash.Untracked[untrackedFilename]);

                Assert.NotNull(stash);
                Assert.Equal("stash@{0}", stash.CanonicalName);
                Assert.Contains("My very first stash", stash.Message);

                var stashRef = repo.Refs["refs/stash"];
                Assert.Equal(stash.WorkTree.Sha, stashRef.TargetIdentifier);

                Assert.False(repo.RetrieveStatus().IsDirty);

                // Create extra file
                untrackedFilename = "stash_candidate.txt";
                Touch(repo.Info.WorkingDirectory, untrackedFilename, "Oh, I'm going to be stashed!\n");

                Stash secondStash = repo.Stashes.Add(stasher, "My second stash", StashModifiers.IncludeUntracked);

                Assert.NotNull(stash);
                Assert.Equal("stash@{0}", stash.CanonicalName);
                Assert.Contains("My second stash", secondStash.Message);

                Assert.Equal(2, repo.Stashes.Count());
                Assert.Equal("stash@{0}", repo.Stashes.First().CanonicalName);
                Assert.Equal("stash@{1}", repo.Stashes.Last().CanonicalName);

                Assert.NotNull(secondStash.Untracked[untrackedFilename]);

                // Stash history has been shifted
                Assert.Equal(repo.Lookup<Commit>("stash@{0}").Sha, secondStash.WorkTree.Sha);
                Assert.Equal(repo.Lookup<Commit>("stash@{1}").Sha, stash.WorkTree.Sha);

                //Remove one stash
                repo.Stashes.Remove(0);
                Assert.Equal(1, repo.Stashes.Count());
                Stash newTopStash = repo.Stashes.First();
                Assert.Equal("stash@{0}", newTopStash.CanonicalName);
                Assert.Equal(stash.WorkTree.Sha, newTopStash.WorkTree.Sha);

                // Stash history has been shifted
                Assert.Equal(stash.WorkTree.Sha, repo.Lookup<Commit>("stash").Sha);
                Assert.Equal(stash.WorkTree.Sha, repo.Lookup<Commit>("stash@{0}").Sha);
            }
        }
Example #4
0
        public void CanAddAndRemoveStash()
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath);
            using (var repo = new Repository(path.RepositoryPath))
            {
                var stasher = DummySignature;

                Assert.True(repo.Index.RetrieveStatus().IsDirty);

                Stash stash = repo.Stashes.Add(stasher, "My very first stash", StashOptions.IncludeUntracked);

                // Check that untracked files are deleted from working directory
                Assert.False(File.Exists(Path.Combine(repo.Info.WorkingDirectory, "new_untracked_file.txt")));

                Assert.NotNull(stash);
                Assert.Equal("stash@{0}", stash.CanonicalName);
                Assert.Contains("My very first stash", stash.Message);

                var stashRef = repo.Refs["refs/stash"];
                Assert.Equal(stash.Target.Sha, stashRef.TargetIdentifier);

                Assert.False(repo.Index.RetrieveStatus().IsDirty);

                // Create extra file
                string newFileFullPath = Path.Combine(repo.Info.WorkingDirectory, "stash_candidate.txt");
                File.WriteAllText(newFileFullPath, "Oh, I'm going to be stashed!\n");

                Stash secondStash = repo.Stashes.Add(stasher, "My second stash", StashOptions.IncludeUntracked);

                Assert.NotNull(stash);
                Assert.Equal("stash@{0}", stash.CanonicalName);
                Assert.Contains("My second stash", secondStash.Message);

                Assert.Equal(2, repo.Stashes.Count());
                Assert.Equal("stash@{0}", repo.Stashes.First().CanonicalName);
                Assert.Equal("stash@{1}", repo.Stashes.Last().CanonicalName);

                // Stash history has been shifted
                Assert.Equal(repo.Lookup<Commit>("stash@{0}").Sha, secondStash.Target.Sha);
                Assert.Equal(repo.Lookup<Commit>("stash@{1}").Sha, stash.Target.Sha);

                //Remove one stash
                repo.Stashes.Remove("stash@{0}");
                Assert.Equal(1, repo.Stashes.Count());
                Stash newTopStash = repo.Stashes.First();
                Assert.Equal("stash@{0}", newTopStash.CanonicalName);
                Assert.Equal(stash.Target.Sha, newTopStash.Target.Sha);

                // Stash history has been shifted
                Assert.Equal(stash.Target.Sha, repo.Lookup<Commit>("stash").Sha);
                Assert.Equal(stash.Target.Sha, repo.Lookup<Commit>("stash@{0}").Sha);
            }
        }
        public void CanFindCommonAncestorForTwoCommitsAsEnumerable()
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var first = repo.Lookup<Commit>("c47800c7266a2be04c571c04d5a6614691ea99bd");
                var second = repo.Lookup<Commit>("9fd738e8f7967c078dceed8190330fc8648ee56a");

                Commit ancestor = repo.Commits.FindCommonAncestor(new[] { first, second });

                Assert.NotNull(ancestor);
                ancestor.Id.Sha.ShouldEqual("5b5b025afb0b4c913b4c338a42934a3863bf3644");
            }
        }
        public void CanFindCommonAncestorForSeveralCommits()
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var first = repo.Lookup<Commit>("4c062a6361ae6959e06292c1fa5e2822d9c96345");
                var second = repo.Lookup<Commit>("be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
                var third = repo.Lookup<Commit>("c47800c7266a2be04c571c04d5a6614691ea99bd");
                var fourth = repo.Lookup<Commit>("5b5b025afb0b4c913b4c338a42934a3863bf3644");

                Commit ancestor = repo.Commits.FindCommonAncestor(new[] { first, second, third, fourth });

                Assert.NotNull(ancestor);
                ancestor.Id.Sha.ShouldEqual("5b5b025afb0b4c913b4c338a42934a3863bf3644");
            }
        }
        public void CanCalculateHistoryDivergenceWhenNoAncestorIsShared(
            string sinceSha, string untilSha,
            int? expectedAheadBy, int? expectedBehindBy)
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var since = repo.Lookup<Commit>(sinceSha);
                var until = repo.Lookup<Commit>(untilSha);

                HistoryDivergence div = repo.ObjectDatabase.CalculateHistoryDivergence(since, until);

                Assert.Equal(expectedAheadBy, div.AheadBy);
                Assert.Equal(expectedBehindBy, div.BehindBy);
                Assert.Null(div.CommonAncestor);
            }
        }
Example #8
0
        public void CanAmendACommitWithMoreThanOneParent()
        {
            string path = CloneStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var mergedCommit = repo.Lookup<Commit>("be3563a");
                Assert.NotNull(mergedCommit);
                Assert.Equal(2, mergedCommit.Parents.Count());

                repo.Reset(ResetOptions.Soft, mergedCommit.Sha);

                CreateAndStageANewFile(repo);
                const string commitMessage = "I'm rewriting the history!";

                Commit amendedCommit = repo.Commit(commitMessage, DummySignature, DummySignature, true);

                AssertCommitHasBeenAmended(repo, amendedCommit, mergedCommit);

                // Assert a reflog entry is created
                var reflogEntry = repo.Refs.Log("HEAD").First();
                Assert.Equal(amendedCommit.Committer, reflogEntry.Commiter);
                Assert.Equal(amendedCommit.Id, reflogEntry.To);
                Assert.Equal(string.Format("commit (amend): {0}", commitMessage), reflogEntry.Message);
            }
        }
Example #9
0
        public void HardResetUpdatesTheContentOfTheWorkingDirectory()
        {
            bool progressCalled = false;

            string path = SandboxStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var names = new DirectoryInfo(repo.Info.WorkingDirectory).GetFileSystemInfos().Select(fsi => fsi.Name).ToList();

                File.Delete(Path.Combine(repo.Info.WorkingDirectory, "README"));
                Touch(repo.Info.WorkingDirectory, "WillNotBeRemoved.txt", "content\n");

                Assert.True(names.Count > 4);

                var commit = repo.Lookup<Commit>("HEAD~3");
                repo.Reset(ResetMode.Hard, commit, new CheckoutOptions()
                {
                    OnCheckoutProgress = (_path, _completed, _total) => { progressCalled = true; },
                });

                names = new DirectoryInfo(repo.Info.WorkingDirectory).GetFileSystemInfos().Select(fsi => fsi.Name).ToList();
                names.Sort(StringComparer.Ordinal);

                Assert.Equal(true, progressCalled);
                Assert.Equal(new[] { ".git", "README", "WillNotBeRemoved.txt", "branch_file.txt", "new.txt", "new_untracked_file.txt" }, names);
            }
        }
Example #10
0
        public void CanArchiveATree()
        {
            string path = SandboxBareTestRepo();
            using (var repo = new Repository(path))
            {
                var tree = repo.Lookup<Tree>("581f9824ecaf824221bd36edf5430f2739a7c4f5");

                var archiver = new MockArchiver();

                var before = DateTimeOffset.Now.TruncateMilliseconds();

                repo.ObjectDatabase.Archive(tree, archiver);

                var expected = new ArrayList
                {
                    new { Path = "1", Sha = "7f76480d939dc401415927ea7ef25c676b8ddb8f" },
                    new { Path = Path.Combine("1", "branch_file.txt"), Sha = "45b983be36b73c0788dc9cbcb76cbb80fc7bb057" },
                    new { Path = "README", Sha = "a8233120f6ad708f843d861ce2b7228ec4e3dec6" },
                    new { Path = "branch_file.txt", Sha = "45b983be36b73c0788dc9cbcb76cbb80fc7bb057" },
                    new { Path = "new.txt", Sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd" },
                };
                Assert.Equal(expected, archiver.Files);
                Assert.Null(archiver.ReceivedCommitSha);
                Assert.InRange(archiver.ModificationTime, before, DateTimeOffset.UtcNow);
            }
        }
Example #11
0
        public void CanArchiveACommitWithDirectoryAsTar()
        {
            var path = SandboxBareTestRepo();
            using (var repo = new Repository(path))
            {
                // This tests generates an archive of the bare test repo, and compares it with
                // a pre-generated tar file. The expected tar file has been generated with the
                // crlf filter active (on windows), so we need to make sure that even if the test
                // is launched on linux then the files content has the crlf filter applied (not
                // active by default).
                var sb = new StringBuilder();
                sb.Append("* text eol=crlf\n");
                Touch(Path.Combine(repo.Info.Path, "info"), "attributes", sb.ToString());

                var commit = repo.Lookup<Commit>("4c062a6361ae6959e06292c1fa5e2822d9c96345");

                var scd = BuildSelfCleaningDirectory();
                var archivePath = Path.Combine(scd.RootedDirectoryPath, Path.GetRandomFileName() + ".tar");
                Directory.CreateDirectory(scd.RootedDirectoryPath);

                repo.ObjectDatabase.Archive(commit, archivePath);

                using (var expectedStream = new StreamReader(Path.Combine(ResourcesDirectory.FullName, "expected_archives/commit_with_directory.tar")))
                using (var actualStream = new StreamReader(archivePath))
                {
                    string expected = expectedStream.ReadToEnd();
                    string actual = actualStream.ReadToEnd();

                    Assert.Equal(expected, actual);
                }
            }
        }
Example #12
0
        public void CanAmendACommitWithMoreThanOneParent()
        {
            string path = CloneStandardTestRepo();
            using (var repo = new Repository(path))
            {
                var mergedCommit = repo.Lookup<Commit>("be3563a");
                Assert.NotNull(mergedCommit);
                Assert.Equal(2, mergedCommit.Parents.Count());

                repo.Reset(ResetMode.Soft, mergedCommit.Sha);

                CreateAndStageANewFile(repo);
                const string commitMessage = "I'm rewriting the history!";

                Commit amendedCommit = repo.Commit(commitMessage, Constants.Signature, Constants.Signature,
                    new CommitOptions { AmendPreviousCommit = true });

                AssertCommitHasBeenAmended(repo, amendedCommit, mergedCommit);

                AssertRefLogEntry(repo, "HEAD",
                                  amendedCommit.Id,
                                  string.Format("commit (amend): {0}", commitMessage),
                                  mergedCommit.Id,
                                  amendedCommit.Committer);
            }
        }
        public void CanExtractStatisticsFromDiff()
        {
            using (var repo = new Repository(StandardTestRepoPath))
            {
                var oldTree = repo.Lookup<Commit>("origin/packed-test").Tree;
                var newTree = repo.Lookup<Commit>("HEAD").Tree;
                var stats = repo.Diff.Compare<PatchStats>(oldTree, newTree);

                Assert.Equal(8, stats.TotalLinesAdded);
                Assert.Equal(1, stats.TotalLinesDeleted);

                var contentStats = stats["new.txt"];
                Assert.Equal(1, contentStats.LinesAdded);
                Assert.Equal(1, contentStats.LinesDeleted);
            }
        }
        public void CanCheckoutAnArbitraryCommit(string commitPointer)
        {
            TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath);
            using (var repo = new Repository(path.RepositoryPath))
            {
                Branch master = repo.Branches["master"];
                Assert.True(master.IsCurrentRepositoryHead);

                // Set the working directory to the current head
                ResetAndCleanWorkingDirectory(repo);

                Assert.False(repo.Index.RetrieveStatus().IsDirty);

                Branch detachedHead = repo.Checkout(commitPointer);

                Assert.Equal(repo.Head, detachedHead);
                Assert.Equal(repo.Lookup(commitPointer).Sha, detachedHead.Tip.Sha);
                Assert.True(repo.Head.IsCurrentRepositoryHead);
                Assert.True(repo.Info.IsHeadDetached);
                Assert.False(repo.Index.RetrieveStatus().IsDirty);

                Assert.True(detachedHead.IsCurrentRepositoryHead);
                Assert.False(detachedHead.IsRemote);
                Assert.Equal(detachedHead.Name, detachedHead.CanonicalName);

                Assert.Equal("(no branch)", detachedHead.CanonicalName);

                Assert.False(master.IsCurrentRepositoryHead);
            }
        }
        public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflictStrategy)
        {
            const string conflictFile = "a.txt";
            const string conflictBranchName = "conflicts";

            string path = CloneMergeTestRepo();
            using (var repo = new Repository(path))
            {
                Branch branch = repo.Branches[conflictBranchName];
                Assert.NotNull(branch);

                CherryPickOptions cherryPickOptions = new CherryPickOptions()
                {
                    FileConflictStrategy = conflictStrategy,
                };

                CherryPickResult result = repo.CherryPick(branch.Tip, Constants.Signature, cherryPickOptions);
                Assert.Equal(CherryPickStatus.Conflicts, result.Status);

                // Get the information on the conflict.
                Conflict conflict = repo.Index.Conflicts[conflictFile];

                Assert.NotNull(conflict);
                Assert.NotNull(conflict.Theirs);
                Assert.NotNull(conflict.Ours);

                // Get the blob containing the expected content.
                Blob expectedBlob = null;
                switch (conflictStrategy)
                {
                    case CheckoutFileConflictStrategy.Theirs:
                        expectedBlob = repo.Lookup<Blob>(conflict.Theirs.Id);
                        break;
                    case CheckoutFileConflictStrategy.Ours:
                        expectedBlob = repo.Lookup<Blob>(conflict.Ours.Id);
                        break;
                    default:
                        throw new Exception("Unexpected FileConflictStrategy");
                }

                Assert.NotNull(expectedBlob);

                // Check the content of the file on disk matches what is expected.
                string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile));
                Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile)));
            }
        }
Example #16
0
 public void CanEnumerateBlobs()
 {
     using (var repo = new Repository(Constants.TestRepoPath))
     {
         var tree = repo.Lookup<Tree>(sha);
         tree.Files.Count().ShouldEqual(3);
     }
 }
Example #17
0
 public void CanLookUpBlob()
 {
     using (var repo = new Repository(BareTestRepoPath))
     {
         var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
         Assert.NotNull(blob);
     }
 }
Example #18
0
 public void CanGetBlobSize()
 {
     using (var repo = new Repository(Constants.BareTestRepoPath))
     {
         var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
         blob.Size.ShouldEqual(10);
     }
 }
Example #19
0
 public void CanEnumerateSubTrees()
 {
     using (var repo = new Repository(Constants.BareTestRepoPath))
     {
         var tree = repo.Lookup<Tree>(sha);
         tree.Trees.Count().ShouldEqual(1);
     }
 }
Example #20
0
 public void CanLookUpBlob()
 {
     using (var repo = new Repository(Constants.BareTestRepoPath))
     {
         var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
         blob.ShouldNotBeNull();
     }
 }
Example #21
0
 public void CanEnumerateSubTrees()
 {
     using (var repo = new Repository(BareTestRepoPath))
     {
         var tree = repo.Lookup<Tree>(sha);
         Assert.Equal(1, tree.Trees.Count());
     }
 }
Example #22
0
 public void CanGetBlobSize()
 {
     using (var repo = new Repository(BareTestRepoPath))
     {
         var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");
         Assert.Equal(10, blob.Size);
     }
 }
        public void CanCalculateHistoryDivergence(
            string sinceSha, string untilSha,
            string expectedAncestorSha, int? expectedAheadBy, int? expectedBehindBy)
        {
            string path = SandboxBareTestRepo();
            using (var repo = new Repository(path))
            {
                var since = repo.Lookup<Commit>(sinceSha);
                var until = repo.Lookup<Commit>(untilSha);

                HistoryDivergence div = repo.ObjectDatabase.CalculateHistoryDivergence(since, until);

                Assert.Equal(expectedAheadBy, div.AheadBy);
                Assert.Equal(expectedBehindBy, div.BehindBy);
                Assert.Equal(expectedAncestorSha, div.CommonAncestor.Id.ToString(7));
            }
        }
Example #24
0
 public void CanLookupACommitByTheNameOfALightweightTag()
 {
     using (var repo = new Repository(Constants.TestRepoPath))
     {
         var gitObject = repo.Lookup("refs/tags/lw");
         gitObject.ShouldNotBeNull();
         Assert.IsInstanceOf<Commit>(gitObject);
     }
 }
        public void FindCommonAncestorForCommitsAsEnumerableThrows(string[] shas, MergeBaseFindingStrategy strategy)
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var commits = shas.Select(sha => sha == "-" ? CreateOrphanedCommit(repo) : repo.Lookup<Commit>(sha)).ToArray();

                Assert.Throws<ArgumentException>(() => repo.Commits.FindMergeBase(commits, strategy));
            }
        }
Example #26
0
 public void CanLookupACommitByTheNameOfABranch()
 {
     using (var repo = new Repository(Constants.TestRepoPath))
     {
         var gitObject = repo.Lookup("refs/heads/master");
         gitObject.ShouldNotBeNull();
         Assert.IsInstanceOf<Commit>(gitObject);
     }
 }
Example #27
0
        public void CanEnumerateTreeEntries()
        {
            using (var repo = new Repository(Constants.BareTestRepoPath))
            {
                var tree = repo.Lookup<Tree>(sha);
                tree.Count().ShouldEqual(tree.Count);

                CollectionAssert.AreEqual(new[] { "1", "README", "branch_file.txt", "new.txt" }, tree.Select(te => te.Name).ToArray());
            }
        }
Example #28
0
        public void CanGetBlobAsUtf8()
        {
            using (var repo = new Repository(Constants.BareTestRepoPath))
            {
                var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");

                var text = blob.ContentAsUtf8();
                text.ShouldEqual("hey there\n");
            }
        }
Example #29
0
        public void CanGetBlobAsUtf8()
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var blob = repo.Lookup<Blob>("a8233120f6ad708f843d861ce2b7228ec4e3dec6");

                string text = blob.ContentAsUtf8();
                Assert.Equal("hey there\n", text);
            }
        }
Example #30
0
        public void CanConvertEntryToTree()
        {
            using (var repo = new Repository(Constants.BareTestRepoPath))
            {
                var tree = repo.Lookup<Tree>(sha);
                TreeEntry treeEntry = tree["1"];

                var subtree = treeEntry.Target as Tree;
                subtree.ShouldNotBeNull();
            }
        }
Example #31
0
        public void RevertFindsRenames(bool?findRenames)
        {
            // The environment is set up such that:
            //   - file d.txt is edited in the commit that is to be reverted (commit A)
            //   - file d.txt is renamed to d_renamed.txt
            //   - commit A is reverted.
            // If rename detection is enabled, then the revert is applied
            // to d_renamed.txt. If rename detection is not enabled,
            // then the revert results in a conflict.
            const string revertBranchName = "refs/heads/revert_rename";
            const string commitIdToRevert = "ca3e813";
            const string expectedBlobId   = "0ff3bbb9c8bba2291654cd64067fa417ff54c508";
            const string modifiedFilePath = "d_renamed.txt";

            string repoPath = CloneRevertTestRepo();

            using (var repo = new Repository(repoPath))
            {
                Branch currentBranch = repo.Checkout(revertBranchName);
                Assert.NotNull(currentBranch);

                Commit commitToRevert = repo.Lookup <Commit>(commitIdToRevert);
                Assert.NotNull(currentBranch);

                RevertOptions options;
                if (findRenames.HasValue)
                {
                    options = new RevertOptions()
                    {
                        FindRenames = findRenames.Value,
                    };
                }
                else
                {
                    options = new RevertOptions();
                }

                RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options);
                Assert.NotNull(result);

                if (!findRenames.HasValue ||
                    findRenames.Value == true)
                {
                    Assert.Equal(RevertStatus.Reverted, result.Status);
                    Assert.NotNull(result.Commit);
                    Blob expectedBlob = repo.Lookup <Blob>(expectedBlobId);
                    Assert.NotNull(expectedBlob);

                    GitObject blob = result.Commit.Tree[modifiedFilePath].Target as Blob;
                    Assert.NotNull(blob);
                    Assert.Equal(blob.Id, expectedBlob.Id);

                    // Verify contents of workspace
                    string fullPath = Path.Combine(repo.Info.WorkingDirectory, modifiedFilePath);
                    Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(modifiedFilePath)), File.ReadAllText(fullPath));
                }
                else
                {
                    Assert.Equal(RevertStatus.Conflicts, result.Status);
                    Assert.Null(result.Commit);
                }
            }
        }
Example #32
0
        private static IEnumerable <Tuple <ObjectId, ObjectId> > SplitRepository(Repository baseRepo, ICommitLog commits, string name, string path, IEnumerable <SharedRepo> sharedRepos, IEnumerable <MergedRepo> mergedRepos)
        {
            var shared = sharedRepos.Where(r => r.Paths.Any(p => p.StartsWith(path + "/"))).Select(r => new
            {
                Repo    = "../" + r.Name + ".git",
                Path    = r.Paths.First(p => p.StartsWith(path + "/")).Substring(path.Length + 1),
                Commits = r.Commits
            });
            var merged = mergedRepos.Where(r => r.Name == name);

            using (var repo = new Repository(Repository.Init(Path.Combine("output", name))))
            {
                File.Copy(Path.Combine(Config.Instance.MainRepo, ".gitignore"), Path.Combine("output", name, ".gitignore"));
                repo.Index.Add(".gitignore");
                File.Copy(Path.Combine(Config.Instance.MainRepo, ".gitattributes"), Path.Combine("output", name, ".gitattributes"));
                repo.Index.Add(".gitattributes");

                foreach (var toMerge in merged)
                {
                    using (var mergeRepo = new Repository(toMerge.Repo))
                    {
                        foreach (var c in mergeRepo.Commits.QueryBy(new CommitFilter {
                            SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
                        }))
                        {
                            bool any = false;

                            foreach (var m in toMerge.Mapping)
                            {
                                if (Merge(repo, c, m.Key, m.Value))
                                {
                                    any = true;
                                }
                            }

                            if (any)
                            {
                                var rewrittenCommit = repo.Commit(c.Message, new Signature(c.Author.Name, Config.Instance.MapEmail(c.Author.Email), c.Author.When), new Signature(c.Committer.Name, Config.Instance.MapEmail(c.Author.Email), c.Author.When), new CommitOptions {
                                    AllowEmptyCommit = true
                                });
                                yield return(new Tuple <ObjectId, ObjectId>(c.Id, rewrittenCommit.Id));
                            }
                        }
                    }
                    repo.Index.Clear();
                    repo.Index.Add(".gitignore");
                    repo.Index.Add(".gitattributes");
                }

                if (shared.Any())
                {
                    File.WriteAllText(Path.Combine("output", name, ".gitmodules"), string.Join("", shared.Select(s => $"[submodule \"{s.Path}\"]\n    path = {s.Path}\n    url = {s.Repo}\n")));
                    repo.Index.Add(".gitmodules");
                }

                foreach (var c in commits)
                {
                    if (c.Tree[path] == null)
                    {
                        continue;
                    }

                    TreeDefinition tree = null;
                    foreach (var s in shared)
                    {
                        var mapping = s.Commits.FirstOrDefault(commit => c.Id == commit.Item1);
                        if (mapping != null)
                        {
                            if (tree == null)
                            {
                                var tempCommit = repo.Commit("temp", new Signature("temp", "*****@*****.**", DateTimeOffset.UtcNow), new Signature("temp", "*****@*****.**", DateTimeOffset.UtcNow), new CommitOptions {
                                    AllowEmptyCommit = true
                                });
                                tree = TreeDefinition.From(tempCommit);
                                repo.Reset(ResetMode.Soft, tempCommit.Parents.First());
                            }
                            tree.AddGitLink(s.Path, mapping.Item2);
                        }
                    }
                    if (tree != null)
                    {
                        repo.Index.Replace(repo.ObjectDatabase.CreateTree(tree));
                    }

                    var oldTree = c.Parents.FirstOrDefault()?.Tree?[path]?.Target as Tree;
                    if (oldTree != null)
                    {
                        var diff = baseRepo.Diff.Compare <TreeChanges>(oldTree, (Tree)c.Tree[path].Target);
                        if (!diff.Any())
                        {
                            continue;
                        }
                        foreach (var file in diff)
                        {
                            if (file.Mode == Mode.Directory)
                            {
                                continue;
                            }

                            if (!file.Exists || (file.OldPath != file.Path && file.Status != ChangeKind.Copied))
                            {
                                if (!shared.Any(s => file.OldPath.Replace('\\', '/').StartsWith(s.Path + '/')))
                                {
                                    File.Delete(Path.Combine("output", name, file.OldPath));
                                    repo.Index.Remove(file.OldPath);
                                }
                            }

                            if (file.Exists)
                            {
                                if (!shared.Any(s => file.Path.Replace('\\', '/').StartsWith(s.Path + '/')))
                                {
                                    Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine("output", name, file.Path)));
                                    using (var input = baseRepo.Lookup <Blob>(file.Oid).GetContentStream())
                                        using (var output = File.Create(Path.Combine("output", name, file.Path)))
                                        {
                                            input.CopyTo(output);
                                        }
                                    repo.Index.Add(file.Path);
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (var entry in RecursiveTree((Tree)c.Tree[path].Target, path))
                        {
                            if (shared.Any(s => entry.Item1.Replace('\\', '/').StartsWith(s.Path + '/')))
                            {
                                continue;
                            }
                            var fullPath = Path.Combine("output", name, entry.Item1);
                            Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
                            using (var content = entry.Item2.GetContentStream())
                                using (var output = File.Create(fullPath))
                                {
                                    content.CopyTo(output);
                                }
                            repo.Index.Add(entry.Item1);
                        }
                    }

                    var email           = Config.Instance.MapEmail(c.Author.Email);
                    var rewrittenCommit = repo.Commit(c.Message, new Signature(c.Author.Name, email, c.Author.When), new Signature(c.Committer.Name, email, c.Author.When), new CommitOptions {
                        AllowEmptyCommit = true
                    });
                    yield return(new Tuple <ObjectId, ObjectId>(c.Id, rewrittenCommit.Id));
                }

                repo.Network.Remotes.Add("origin", Config.Instance.Origin(name));

                Console.WriteLine("Copying LFS files...");
                var lfsCount = CopyLfsFiles(repo, Path.Combine("output", name, ".git", "lfs", "objects"), new[] { Path.Combine(baseRepo.Info.WorkingDirectory, ".git", "lfs", "objects") }.Concat(merged.Where(r => r.Name == name).Select(r => Path.Combine(r.Repo, ".git", "lfs", "objects"))));
                Console.WriteLine($"Copied {lfsCount} files.");

                // LibGit2Sharp doesn't support git gc, so we use the command line:
                using (var gc = Process.Start(new ProcessStartInfo("git", "gc --aggressive")
                {
                    WorkingDirectory = repo.Info.WorkingDirectory,
                    UseShellExecute = false
                }))
                {
                    gc.WaitForExit();
                }
            }
        }
Example #33
0
        public void CanContinueRebase()
        {
            SelfCleaningDirectory scd = BuildSelfCleaningDirectory();
            var path = Repository.Init(scd.DirectoryPath);

            using (Repository repo = new Repository(path))
            {
                ConstructRebaseTestRepository(repo);

                repo.Checkout(topicBranch1Name);
                Assert.False(repo.RetrieveStatus().IsDirty);

                Branch branch   = repo.Branches[topicBranch1Name];
                Branch upstream = repo.Branches[conflictBranch1Name];
                Branch onto     = repo.Branches[conflictBranch1Name];

                int  beforeStepCallCount       = 0;
                int  afterStepCallCount        = 0;
                bool wasCheckoutProgressCalled = false;
                bool wasCheckoutNotifyCalled   = false;

                RebaseOptions options = new RebaseOptions()
                {
                    RebaseStepStarting  = x => beforeStepCallCount++,
                    RebaseStepCompleted = x => afterStepCallCount++,
                    OnCheckoutProgress  = (x, y, z) => wasCheckoutProgressCalled = true,
                    OnCheckoutNotify    = (x, y) => { wasCheckoutNotifyCalled = true; return(true); },
                    CheckoutNotifyFlags = CheckoutNotifyFlags.Updated,
                };

                RebaseResult rebaseResult = repo.Rebase.Start(branch, upstream, onto, Constants.Identity, options);

                // Verify that we have a conflict.
                Assert.Equal(CurrentOperation.RebaseMerge, repo.Info.CurrentOperation);
                Assert.Equal(RebaseStatus.Conflicts, rebaseResult.Status);
                Assert.True(repo.RetrieveStatus().IsDirty);
                Assert.False(repo.Index.IsFullyMerged);
                Assert.Equal(0, rebaseResult.CompletedStepCount);
                Assert.Equal(3, rebaseResult.TotalStepCount);

                // Verify that expected callbacks were called
                Assert.Equal(1, beforeStepCallCount);
                Assert.Equal(0, afterStepCallCount);
                Assert.True(wasCheckoutProgressCalled, "CheckoutProgress callback was not called.");

                // Resolve the conflict
                foreach (Conflict conflict in repo.Index.Conflicts)
                {
                    Touch(repo.Info.WorkingDirectory,
                          conflict.Theirs.Path,
                          repo.Lookup <Blob>(conflict.Theirs.Id).GetContentText(new FilteringOptions(conflict.Theirs.Path)));
                    Commands.Stage(repo, conflict.Theirs.Path);
                }

                Assert.True(repo.Index.IsFullyMerged);

                // Clear the flags:
                wasCheckoutProgressCalled = false; wasCheckoutNotifyCalled = false;
                RebaseResult continuedRebaseResult = repo.Rebase.Continue(Constants.Identity, options);

                Assert.NotNull(continuedRebaseResult);
                Assert.Equal(RebaseStatus.Complete, continuedRebaseResult.Status);
                Assert.False(repo.RetrieveStatus().IsDirty);
                Assert.True(repo.Index.IsFullyMerged);
                Assert.Equal(0, rebaseResult.CompletedStepCount);
                Assert.Equal(3, rebaseResult.TotalStepCount);

                Assert.Equal(3, beforeStepCallCount);
                Assert.Equal(3, afterStepCallCount);
                Assert.True(wasCheckoutProgressCalled, "CheckoutProgress callback was not called.");
                Assert.True(wasCheckoutNotifyCalled, "CheckoutNotify callback was not called.");
            }
        }
Example #34
0
        private void CommitHistory()
        {
            Database   db = new Database();
            Repository repo;
            //List<Entities.Commit> commiList
            //Entities.Commit commit;
            //CommitFile commitFile;
            NotificationArgs notificationArgs;

            var directories = Directory.GetDirectories(downloadDirectory);

            int counter   = 0;
            int groupSize = Convert.ToInt32(Math.Ceiling(directories.Count() / 3.0));

            var result      = directories.GroupBy(s => counter++ / groupSize).Select(g => g.ToArray()).ToList();
            int threadCount = result.Count() + 1;

            Parallel.For(0, threadCount, i =>
            {
                var dataSet = result.ElementAtOrDefault(i);
                if (dataSet != null)
                {
                    Console.WriteLine("Processing dataset: " + i + "; Count: " + dataSet.Count());
                    foreach (var directory in dataSet)
                    {
                        string lastFolderName = Path.GetFileName(directory);
                        long appId            = db.GetAppByName(lastFolderName).Id;
                        try
                        {
                            repo = new Repository(directory);
                            List <Entities.Commit> commiList = new List <Entities.Commit>();

                            int commitCount = repo.Commits.Count();

                            notificationArgs = new NotificationArgs(string.Format("Started - Commit Histroy for {0} - Total Commits: {1}", lastFolderName, commitCount), DateTime.Now, NotificationType.INFORMATION);
                            OnMessageIssued(notificationArgs);

                            int j = repo.Commits.Count() - 1;
                            foreach (var cx in repo.Commits)
                            // for (int i = commitCount - 1; i >= 0; i--)
                            {
                                Entities.Commit commit = new Entities.Commit();
                                commit.AuthorEmail     = cx.Author.Email;
                                commit.AuthorEmail     = cx.Author.Email;
                                commit.AuthorName      = cx.Author.Name;
                                commit.Date            = cx.Author.When.LocalDateTime;
                                commit.Message         = cx.Message;
                                commit.GUID            = cx.Sha;

                                if (includeFiles)
                                {
                                    if (j == commitCount - 1)
                                    {
                                        Tree firstCommit = repo.Lookup <Tree>(repo.Commits.ElementAt(j).Tree.Sha);
                                        Tree lastCommit  = repo.Lookup <Tree>(repo.Commits.ElementAt(0).Tree.Sha);

                                        var changes = repo.Diff.Compare <TreeChanges>(lastCommit, firstCommit);
                                        foreach (var item in changes)
                                        {
                                            if (item.Status != ChangeKind.Deleted)
                                            {
                                                CommitFile commitFile = new CommitFile(item.Path, ChangeKind.Added.ToString());
                                                commit.CommitFiles.Add(commitFile);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        var changes = repo.Diff.Compare <TreeChanges>(repo.Commits.ElementAt(j + 1).Tree, repo.Commits.ElementAt(j).Tree);
                                        foreach (var item in changes)
                                        {
                                            CommitFile commitFile = new CommitFile(item.Path, item.Status.ToString());
                                            commit.CommitFiles.Add(commitFile);
                                        }
                                    }
                                }

                                commiList.Add(commit);

                                j--;
                            }

                            db.BatchInsertCommits(commiList, appId);

                            notificationArgs = new NotificationArgs(string.Format("Completed - Commit Histroy for {0}", lastFolderName), DateTime.Now, NotificationType.SUCCESS);
                            OnMessageIssued(notificationArgs);
                        }
                        catch (Exception error)
                        {
                            LogFailure(string.Format("Failed - Commit Histroy for {0} ; {1}", lastFolderName, error.Message));
                            notificationArgs = new NotificationArgs("Failed -  Commit Histroy for " + lastFolderName, DateTime.Now, NotificationType.FAILURE);
                            OnMessageIssued(notificationArgs);
                            continue;
                        }
                    }
                }
            });
        }
Example #35
0
 private Blob Upvote(Repository repo)
 {
     return(repo.Lookup <Blob>(repo.Tags[UPVOTE].Target.Id));
 }
Example #36
0
        private MonitoredPath GetMonitoredPath(string commitId, MonitoredPath monitoredPath, DirectoryInfo[] directoriesToScan, string branchName)
        {
            MonitoredPath    newmonitoredPath = new MonitoredPath();
            List <GitCommit> commits          = new List <GitCommit>();

            foreach (DirectoryInfo dir in directoriesToScan)
            {
                try
                {
                    GitRepository gitrepo = this.TryGetRepo(monitoredPath, dir.Name);
                    using (Repository repo = new Repository(dir.FullName))
                    {
                        try
                        {
                            string branch = repo.Info.IsBare ? branchName : $"origin/{branchName}";
                            gitrepo.Branch = branch;

                            int    commitCount = 0;
                            Commit com         = repo.Lookup <Commit>(commitId);

                            if (com != null)
                            {
                                CommitFilter comFilter = new CommitFilter
                                {
                                    IncludeReachableFrom = branch,
                                    ExcludeReachableFrom = com
                                };

                                var coms = repo.Commits.QueryBy(comFilter).OrderBy(s => s.Author.When);

                                string repositoryUrl = string.Empty;
                                if (repo.Network.Remotes?["origin"] != null)
                                {
                                    repositoryUrl = repo.Network.Remotes["origin"].Url;
                                }

                                foreach (Commit cm in coms)
                                {
                                    if (!monitoredPath.IncludeMergeCommits)
                                    {
                                        // filter out merge commits
                                        if (com.Parents.Count() > 1)
                                        {
                                            continue;
                                        }
                                    }

                                    commits.Add(new GitCommit
                                    {
                                        Author                 = cm.Author.Name,
                                        AuthorEmail            = string.IsNullOrWhiteSpace(com.Author.Email) ? string.Empty : cm.Author.Email,
                                        AuthorWhen             = cm.Author.When.UtcDateTime,
                                        Committer              = cm.Committer.Name,
                                        CommitterEmail         = string.IsNullOrWhiteSpace(com.Committer.Email) ? string.Empty : cm.Committer.Email,
                                        CommitterWhen          = cm.Committer.When.UtcDateTime,
                                        Sha                    = cm.Sha,
                                        Message                = cm.Message,
                                        RepositoryFriendlyName = gitrepo.FriendlyName,
                                        RepositoryName         = dir.Name,
                                        RepositoryUrl          = repositoryUrl,
                                        CommitUrl              = string.IsNullOrWhiteSpace(gitrepo.CommitUrl) ? string.Empty : string.Format($"{gitrepo.CommitUrl}{cm.Sha}"),
                                        IsMerge                = com.Parents.Count() > 1
                                    });
                                    commitCount++;
                                }

                                gitrepo.CommitCount = commitCount;
                                newmonitoredPath.Repositories.Add(gitrepo);
                            }
                        }
                        catch (Exception ex)
                        {
                            this.locallogger.LogError("GetMonitoredPath Bad - ", ex);
                        }

                        newmonitoredPath.Name        = monitoredPath.Name;
                        newmonitoredPath.AllowFetch  = monitoredPath.AllowFetch;
                        newmonitoredPath.AllFolders  = monitoredPath.AllFolders;
                        newmonitoredPath.Path        = monitoredPath.Path;
                        newmonitoredPath.CommitCount = commits.Count;
                        newmonitoredPath.Commits     = commits;
                    }
                }
                catch (Exception ex)
                {
                    this.locallogger.LogError("GetMonitoredPath Bad - ", ex);
                }
            }

            return(newmonitoredPath);
        }
Example #37
0
        static int Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += (sender, e) => Console.Error.WriteLine($"Error: {e.ToString()}");

            if (args.Length != 4)
            {
                Console.Error.WriteLine($"ERROR: Expected 4 arguments but got {args.Length}");
                return(1);
            }

            if (args[0] != "-prev" || args[2] != "-curr")
            {
                Console.Error.WriteLine("ERROR: Invalid arguments. Invoke `prfinder -prev {sha} -curr {sha}`");
                return(1);
            }

            var previousCommitSha = args[1];
            var currentCommitSha  = args[3];

            using (var repo = new Repository(Environment.CurrentDirectory))
            {
                var currentCommit  = repo.Lookup <Commit>(currentCommitSha);
                var previousCommit = repo.Lookup <Commit>(previousCommitSha);

                if (currentCommit is null || previousCommit is null)
                {
                    Console.WriteLine($"Couldn't find commit {(currentCommit is null ? currentCommitSha : previousCommitSha)}");
                    Console.WriteLine("Fetching and trying again...");

                    // it doesn't please me to do this, but libgit2sharp doesn't support ssh easily
                    Process.Start("git", "fetch --all").WaitForExit();
                    Console.WriteLine("--- end of git output ---");
                    Console.WriteLine();

                    currentCommit  = repo.Lookup <Commit>(currentCommitSha);
                    previousCommit = repo.Lookup <Commit>(previousCommitSha);
                }

                // Get commit history starting at the current commit and ending at the previous commit
                var commitLog = repo.Commits.QueryBy(
                    new CommitFilter
                {
                    IncludeReachableFrom = currentCommit,
                    ExcludeReachableFrom = previousCommit
                });

                Console.WriteLine($@"Changes since [{previousCommitSha}]({RepoPRUrl}/commit/{previousCommitSha})");

                foreach (var commit in commitLog)
                {
                    // Exclude auto-merges
                    if (commit.Author.Name == "dotnet-automerge-bot")
                    {
                        continue;
                    }

                    var match = IsMergePRCommit.Match(commit.MessageShort);

                    if (!match.Success)
                    {
                        match = IsSquashedPRCommit.Match(commit.MessageShort);
                    }

                    if (!match.Success)
                    {
                        continue;
                    }

                    var prNumber = match.Groups[1].Value;
                    var prLink   = $@"- [{commit.MessageShort}]({RepoPRUrl}/pull/{prNumber})";

                    Console.WriteLine(prLink);
                }
            }

            return(0);
        }
 /// <summary>
 /// This is just a base function to recurse from.
 /// </summary>
 private static void SafeCheckoutByIndividualFiles(Repository repo, string commit, CheckoutOptions options, ILogger log)
 {
     log.LogDebug($"Beginning individual file checkout for {repo.Info.WorkingDirectory} at {commit}");
     SafeCheckoutTreeByIndividualFiles(repo, repo.Lookup(commit).Peel <Tree>(), "", commit, options, log);
 }
Example #39
0
        public IEnumerable <HunkRangeInfo> GetGitDiffFor(ITextDocument textDocument, string originalPath, ITextSnapshot snapshot)
        {
            var filename       = textDocument.FilePath;
            var repositoryPath = GetGitRepository(Path.GetFullPath(filename), ref originalPath);

            if (repositoryPath == null)
            {
                yield break;
            }

            using (var repo = new Repository(repositoryPath))
            {
                var workingDirectory = repo.Info.WorkingDirectory;
                if (workingDirectory == null)
                {
                    yield break;
                }

                var retrieveStatus = repo.RetrieveStatus(originalPath);
                if (retrieveStatus == FileStatus.Nonexistent)
                {
                    // this occurs if a file within the repository itself (not the working copy) is opened.
                    yield break;
                }

                if ((retrieveStatus & FileStatus.Ignored) != 0)
                {
                    // pointless to show diffs for ignored files
                    yield break;
                }

                // Determine 'from' tree.
                var    currentBranch   = repo.Head.FriendlyName;
                var    baseCommitEntry = repo.Config.Get <string>(string.Format("branch.{0}.diffmarginbase", currentBranch));
                Commit from            = null;
                if (baseCommitEntry != null)
                {
                    var baseCommit = repo.Lookup <Commit>(baseCommitEntry.Value);
                    if (baseCommit != null)
                    {
                        // Found a merge base to diff from.
                        from = baseCommit;
                    }
                }

                if (from == null &&
                    retrieveStatus == FileStatus.Unaltered &&
                    !textDocument.IsDirty &&
                    Path.GetFullPath(filename) == originalPath)
                {
                    // Truly unaltered. The `IsDirty` check isn't valid for cases where the textDocument is a view of a
                    // temporary copy of the file, since the temporary copy could have been made using unsaved changes
                    // and still appear "not dirty".
                    yield break;
                }

                var content = GetCompleteContent(textDocument, snapshot);
                if (content == null)
                {
                    yield break;
                }

                using (var currentContent = new MemoryStream(content))
                {
                    var relativeFilepath = originalPath;
                    if (relativeFilepath.StartsWith(workingDirectory, StringComparison.OrdinalIgnoreCase))
                    {
                        relativeFilepath = relativeFilepath.Substring(workingDirectory.Length);
                    }

                    relativeFilepath = relativeFilepath.Replace('\\', '/');

                    var newBlob = repo.ObjectDatabase.CreateBlob(currentContent, relativeFilepath);

                    bool suppressRollback;
                    Blob blob;

                    if ((retrieveStatus & FileStatus.NewInWorkdir) != 0 || (retrieveStatus & FileStatus.NewInIndex) != 0)
                    {
                        suppressRollback = true;

                        // special handling for added files (would need updating to compare against index)
                        using (var emptyContent = new MemoryStream())
                        {
                            blob = repo.ObjectDatabase.CreateBlob(emptyContent, relativeFilepath);
                        }
                    }
                    else
                    {
                        suppressRollback = false;

                        from = from ?? repo.Head.Tip;
                        TreeEntry fromEntry = from[relativeFilepath];
                        if (fromEntry == null)
                        {
                            // try again using case-insensitive comparison
                            Tree tree = from.Tree;
                            foreach (string segment in relativeFilepath.Split('/'))
                            {
                                if (tree == null)
                                {
                                    yield break;
                                }

                                fromEntry = tree.FirstOrDefault(i => string.Equals(segment, i.Name, StringComparison.OrdinalIgnoreCase));
                                if (fromEntry == null)
                                {
                                    yield break;
                                }

                                tree = fromEntry.Target as Tree;
                            }
                        }

                        blob = fromEntry.Target as Blob;
                        if (blob == null)
                        {
                            yield break;
                        }
                    }

                    var treeChanges = repo.Diff.Compare(blob, newBlob, new CompareOptions {
                        ContextLines = ContextLines, InterhunkLines = 0
                    });

                    var gitDiffParser  = new GitDiffParser(treeChanges.Patch, ContextLines, suppressRollback);
                    var hunkRangeInfos = gitDiffParser.Parse();

                    foreach (var hunkRangeInfo in hunkRangeInfos)
                    {
                        yield return(hunkRangeInfo);
                    }
                }
            }
        }
        public void FindCommonAncestorForCommitsAsEnumerable(string result, string[] shas, MergeBaseFindingStrategy strategy)
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var commits = shas.Select(sha => sha == "-" ? CreateOrphanedCommit(repo) : repo.Lookup <Commit>(sha)).ToArray();

                Commit ancestor = repo.Commits.FindMergeBase(commits, strategy);

                if (result == null)
                {
                    Assert.Null(ancestor);
                }
                else
                {
                    Assert.NotNull(ancestor);
                    Assert.Equal(result, ancestor.Id.Sha);
                }
            }
        }
Example #41
0
        public void StartExternalDiff(ITextDocument textDocument, string originalPath)
        {
            if (textDocument == null || string.IsNullOrEmpty(textDocument.FilePath))
            {
                return;
            }

            var filename       = textDocument.FilePath;
            var repositoryPath = GetGitRepository(Path.GetFullPath(filename), ref originalPath);

            if (repositoryPath == null)
            {
                return;
            }

            using (var repo = new Repository(repositoryPath))
            {
                string workingDirectory = repo.Info.WorkingDirectory;
                string relativePath     = originalPath;
                if (relativePath.StartsWith(workingDirectory, StringComparison.OrdinalIgnoreCase))
                {
                    relativePath = relativePath.Substring(workingDirectory.Length);
                }

                // the name of the object in the database
                string objectName = Path.GetFileName(filename);

                Blob oldBlob    = null;
                var  indexEntry = repo.Index[relativePath.Replace("\\", "/")];
                if (indexEntry != null)
                {
                    objectName = Path.GetFileName(indexEntry.Path);
                    oldBlob    = repo.Lookup <Blob>(indexEntry.Id);
                }

                var tempFileName = Path.GetTempFileName();
                if (oldBlob != null)
                {
                    File.WriteAllText(tempFileName, oldBlob.GetContentText(new FilteringOptions(relativePath)), GetEncoding(filename));
                }

                IVsDifferenceService differenceService = _serviceProvider.GetService(typeof(SVsDifferenceService)) as IVsDifferenceService;
                string leftFileMoniker = tempFileName;
                // The difference service will automatically load the text from the file open in the editor, even if
                // it has changed. Don't use the original path here.
                string rightFileMoniker = filename;

                string actualFilename = objectName;
                string tempPrefix     = Path.GetRandomFileName().Substring(0, 5);
                string caption        = string.Format("{0}_{1} vs. {1}", tempPrefix, actualFilename);

                string tooltip = null;

                string leftLabel;
                if (indexEntry != null)
                {
                    // determine if the file has been staged
                    string revision;
                    var    stagedMask = FileStatus.NewInIndex | FileStatus.ModifiedInIndex;
                    if ((repo.RetrieveStatus(relativePath) & stagedMask) != 0)
                    {
                        revision = "index";
                    }
                    else
                    {
                        revision = repo.Head.Tip.Sha.Substring(0, 7);
                    }

                    leftLabel = string.Format("{0}@{1}", objectName, revision);
                }
                else if (oldBlob != null)
                {
                    // file was added
                    leftLabel = null;
                }
                else
                {
                    // we just compared to head
                    leftLabel = string.Format("{0}@{1}", objectName, repo.Head.Tip.Sha.Substring(0, 7));
                }

                string rightLabel = originalPath;

                string inlineLabel = null;
                string roles       = null;
                __VSDIFFSERVICEOPTIONS grfDiffOptions = __VSDIFFSERVICEOPTIONS.VSDIFFOPT_LeftFileIsTemporary;
                differenceService.OpenComparisonWindow2(leftFileMoniker, rightFileMoniker, caption, tooltip, leftLabel, rightLabel, inlineLabel, roles, (uint)grfDiffOptions);

                // Since the file is marked as temporary, we can delete it now
                File.Delete(tempFileName);
            }
        }
        public void Y()
        {
            _repo.OnBranch("master", r =>
            {
                r.Commit(JohnSmith, "M1", rf =>
                {
                    rf.SetFile(File1, "block1\n\nblock2\n");
                    rf.Stage(File1);
                }).Ref("mark/m/1");
            });

            _repo.OnBranch("branch", r =>
            {
                r.Commit(JohnDoe, "B1", rf =>
                {
                    rf.SetFile(File1, "block1\n\nblock2\nline2.1\nline2.2\n");
                    rf.Stage(File1);
                }).Ref("mark/b/1");
            });

            _repo.OnBranch("master", r =>
            {
                r.Commit(JohnSmith, "M2", rf =>
                {
                    rf.SetFile(File1, "block1\nline1.1\nline1.2\n\nblock2\n");
                    rf.Stage(File1);
                }).Ref("mark/m/2");
            });

            _repo.OnBranch("branch", r =>
            {
                var mr = r.Merge(r.Branches["master"], JohnDoe);

                Console.WriteLine(mr);
                Assert.That(mr.Status, Is.EqualTo(MergeStatus.NonFastForward));

                r.Refs.Add("mark/b/2m", mr.Commit.Id);

                r.Commit(JohnDoe, "B2", rc =>
                {
                    rc.AppendFile(File1, "\nblock3\nline3.1\nline3.2\n");
                    rc.Stage(File1);
                }).Ref("mark/b/3");
            });

            //var diff = _repo.NiceDiff(File1, "mark/b/1", "mark/b/3");

            //PrintDiffText(_repo.CatFile(File1, "mark/b/1"), diff);

            var diff1 = _repo.Diff.Compare <Patch>(
                (_repo.Lookup <Commit>("mark/b/1").Tree),
                (_repo.Lookup <Commit>("mark/b/3").Tree)
                );

            Console.WriteLine(diff1.Content);

            var mb1 = _repo.Lookup <Commit>("mark/m/1");
            var mb2 = _repo.Lookup <Commit>("mark/b/2m");

            var diff2 = _repo.Diff.Compare <Patch>(
                (mb1.Tree),
                (mb2.Tree)
                );

            Console.WriteLine("\n\n\n===================\n\n\n");
            Console.WriteLine(diff2.Content);
        }
Example #43
0
 public GitCommit GetCommit(string commitish)
 {
     return(new GitCommit(_repository.Lookup <Commit>(commitish)));
 }
Example #44
0
        static public LoadFromUrlResult LoadFromUrl(string sourceUrl)
        {
            var parsedUrl = ParseGitHubObjectUrl(sourceUrl);

            if (parsedUrl == null)
                return new LoadFromUrlResult
                {
                    Error = "Failed to parse string '" + sourceUrl + "' as GitHub object URL.",
                };

            var refLooksLikeCommit = Regex.IsMatch(parsedUrl.@ref, "[A-Fa-f0-9]{40}");

            var tempWorkingDirectory = Kalmit.Filesystem.CreateRandomDirectoryInTempDirectory();

            var gitRepositoryLocalDirectory = Path.Combine(tempWorkingDirectory, "git-repository");

            //  https://github.com/libgit2/libgit2sharp/wiki/git-clone
            Repository.Clone(parsedUrl.repository, gitRepositoryLocalDirectory, new CloneOptions { Checkout = false });

            Composition.TreeComponent literalNodeObject = null;
            string urlInCommit = null;
            string urlInFirstParentCommitWithSameValueAtThisPath = null;
            (string hash, CommitContent content)? rootCommit = null;
            (string hash, CommitContent content)? firstParentCommitWithSameTree = null;

            using (var gitRepository = new Repository(gitRepositoryLocalDirectory))
            {
                var commit = gitRepository.Lookup(parsedUrl.@ref) as Commit;

                if (commit == null)
                    return new LoadFromUrlResult
                    {
                        Error = "I did not find the commit for ref '" + parsedUrl.@ref + "'.",
                    };

                urlInCommit = BackToUrl(parsedUrl.WithRef(commit.Sha));

                rootCommit = GetCommitHashAndContent(commit);

                var pathNodesNames = parsedUrl.path.Split('/', StringSplitOptions.RemoveEmptyEntries);

                var findGitObjectResult =
                    FindGitObjectAtPath(commit.Tree, pathNodesNames);

                var linkedObject = findGitObjectResult?.Success;

                if (linkedObject == null)
                    return new LoadFromUrlResult
                    {
                        Error = "I did not find an object at path '" + parsedUrl.path + "'.",
                    };

                IEnumerable<Commit> traceBackTreeParents()
                {
                    var queue = new Queue<Commit>();

                    queue.Enqueue(commit);

                    while (queue.TryDequeue(out var currentCommit))
                    {
                        yield return currentCommit;

                        foreach (var parent in currentCommit.Parents)
                        {
                            if (FindGitObjectAtPath(parent.Tree, pathNodesNames)?.Success?.Sha != linkedObject?.Sha)
                                continue;

                            queue.Enqueue(parent);
                        }
                    }
                }

                firstParentCommitWithSameTree =
                    GetCommitHashAndContent(traceBackTreeParents().OrderBy(commit => commit.Author.When).First());

                urlInFirstParentCommitWithSameValueAtThisPath =
                    BackToUrl(parsedUrl.WithRef(firstParentCommitWithSameTree.Value.hash));
        public void FindCommonAncestorForCommitsAsEnumerableThrows(string[] shas, MergeBaseFindingStrategy strategy)
        {
            using (var repo = new Repository(BareTestRepoPath))
            {
                var commits = shas.Select(sha => sha == "-" ? CreateOrphanedCommit(repo) : repo.Lookup <Commit>(sha)).ToArray();

                Assert.Throws <ArgumentException>(() => repo.Commits.FindMergeBase(commits, strategy));
            }
        }
    static public Result <string, LoadFromUrlSuccess> LoadFromUrl(
        string sourceUrl,
        Func <GetRepositoryFilesPartialForCommitRequest, IImmutableDictionary <IImmutableList <string>, IReadOnlyList <byte> > > getRepositoryFilesPartialForCommit)
    {
        var parsedUrl = ParseUrl(sourceUrl);

        if (parsedUrl == null)
        {
            return(Result <string, LoadFromUrlSuccess> .err(
                       "Failed to parse string '" + sourceUrl + "' as GitHub or GitLab URL."));
        }

        string?branchName         = null;
        bool   refLooksLikeCommit = false;

        if (parsedUrl.inRepository != null)
        {
            refLooksLikeCommit = Regex.IsMatch(parsedUrl.inRepository.@ref, "[A-Fa-f0-9]{40}");

            branchName = refLooksLikeCommit ? null : parsedUrl.inRepository.@ref;
        }

        var cloneUrl = parsedUrl.repository.TrimEnd('/') + ".git";

        if (getRepositoryFilesPartialForCommit == null)
        {
            getRepositoryFilesPartialForCommit =
                req => GetRepositoryFilesPartialForCommitViaLibGitSharpCheckout(
                    cloneUrl: req.cloneUrlCandidates[0],
                    commit: req.commit);
        }

        var repositoryFilesPartial =
            refLooksLikeCommit ?
            getRepositoryFilesPartialForCommit(
                new GetRepositoryFilesPartialForCommitRequest(
                    commit: parsedUrl.inRepository !.@ref,
                    cloneUrlCandidates: ImmutableList.Create(cloneUrl)))
            :
            GetRepositoryFilesPartialForBranchViaLibGitSharpCheckout(cloneUrl, branchName);

        var tempWorkingDirectory        = Filesystem.CreateRandomDirectoryInTempDirectory();
        var gitRepositoryLocalDirectory = Path.Combine(tempWorkingDirectory, "git-repository");

        try
        {
            foreach (var fileWithPath in repositoryFilesPartial)
            {
                var absoluteFilePath      = Path.Combine(new[] { gitRepositoryLocalDirectory }.Concat(fileWithPath.Key).ToArray());
                var absoluteDirectoryPath = Path.GetDirectoryName(absoluteFilePath) !;

                Directory.CreateDirectory(absoluteDirectoryPath);
                File.WriteAllBytes(absoluteFilePath, fileWithPath.Value.ToArray());
            }

            (string hash, CommitContent content)? rootCommit = null;

            using var gitRepository = new Repository(gitRepositoryLocalDirectory);

            Commit?startCommit = null;

            if (parsedUrl.inRepository == null)
            {
                startCommit = gitRepository.Head.Commits.FirstOrDefault();

                if (startCommit == null)
                {
                    return(Result <string, LoadFromUrlSuccess> .err(
                               "Failed to get the first commit from HEAD"));
                }
            }
            else
            {
                startCommit = gitRepository.Lookup(parsedUrl.inRepository.@ref) as Commit;

                if (startCommit == null)
                {
                    return(Result <string, LoadFromUrlSuccess> .err(
                               "I did not find the commit for ref '" + parsedUrl.inRepository.@ref + "'."));
                }
            }

            ParsedUrlInRepository partInRepositoryWithCommit(Commit replacementCommit) =>
            parsedUrl.inRepository == null ?
            new ParsedUrlInRepository(GitObjectType.tree, @ref: replacementCommit.Sha, path: "") :
            parsedUrl.inRepository with
            {
                @ref = replacementCommit.Sha
            };

            var urlInCommit = BackToUrl(parsedUrl with {
                inRepository = partInRepositoryWithCommit(startCommit)
            });

            rootCommit = GetCommitHashAndContent(startCommit);

            var parsedUrlPath =
                parsedUrl.inRepository == null ? "" : parsedUrl.inRepository.path;

            var pathNodesNames = parsedUrlPath.Split('/', StringSplitOptions.RemoveEmptyEntries);

            var findGitObjectResult =
                FindGitObjectAtPath(startCommit.Tree, pathNodesNames);

            var linkedObject = findGitObjectResult?.Ok;

            if (linkedObject == null)
            {
                return(Result <string, LoadFromUrlSuccess> .err(
                           "I did not find an object at path '" + parsedUrlPath + "' in " + startCommit.Sha));
            }

            IEnumerable <Commit> traceBackTreeParents()
            {
                var queue = new Queue <Commit>();

                queue.Enqueue(startCommit);

                while (queue.TryDequeue(out var currentCommit))
                {
                    yield return(currentCommit);

                    foreach (var parent in currentCommit.Parents)
                    {
                        if (FindGitObjectAtPath(parent.Tree, pathNodesNames)?.Ok?.Sha != linkedObject?.Sha)
                        {
                            continue;
                        }

                        queue.Enqueue(parent);
                    }
                }
            }

            var firstParentCommitWithSameTreeRef =
                traceBackTreeParents().OrderBy(commit => commit.Author.When).First();

            var firstParentCommitWithSameTree =
                GetCommitHashAndContent(firstParentCommitWithSameTreeRef);

            var urlInFirstParentCommitWithSameValueAtThisPath =
                BackToUrl(parsedUrl with {
                inRepository = partInRepositoryWithCommit(firstParentCommitWithSameTreeRef)
            });
Example #47
0
        public TreeEntryModel GetBlob(String path)
        {
            String referenceName;
            var    commit = GetCommitByPath(ref path, out referenceName);

            if (commit == null)
            {
                return(null);
            }

            var entry = commit[path];

            if (entry == null || entry.TargetType != TreeEntryTargetType.Blob)
            {
                return(null);
            }

            var blob = (Blob)entry.Target;

            var cacheAccessor = GitCacheAccessor.Singleton(new LastCommitAccessor(_repoId, _repository, commit, path));
            var lastCommitSha = cacheAccessor.Result.Value;

            if (lastCommitSha != commit.Sha)
            {
                commit = _repository.Lookup <Commit>(lastCommitSha);
            }

            var data      = blob.GetContentStream().ToBytes();
            var encoding  = FileHelper.DetectEncoding(data, CpToEncoding(commit.Encoding), _i18n.Value);
            var extension = Path.GetExtension(entry.Name).ToLower();
            var model     = new TreeEntryModel
            {
                Name          = entry.Name,
                ReferenceName = referenceName,
                Sha           = commit.Sha,
                Path          = String.IsNullOrEmpty(path) ? "" : path,
                Commit        = new CommitModel
                {
                    Sha                = commit.Sha,
                    Author             = commit.Author,
                    Committer          = commit.Committer,
                    CommitMessage      = commit.Message.RepetitionIfEmpty(UnknowString),
                    CommitMessageShort = commit.MessageShort.RepetitionIfEmpty(UnknowString),
                    Parents            = commit.Parents.Select(s => s.Sha).ToArray()
                },
                EntryType   = entry.TargetType,
                RawData     = data,
                SizeString  = FileHelper.GetSizeString(data.Length),
                TextContent = encoding == null
                    ? null
                    : FileHelper.ReadToEnd(data, encoding),
                TextBrush = FileHelper.BrushMapping.ContainsKey(extension)
                    ? FileHelper.BrushMapping[extension]
                    : "no-highlight",
                BlobType = encoding == null
                    ? FileHelper.ImageSet.Contains(extension)
                        ? BlobType.Image
                        : BlobType.Binary
                    : extension == ".md"
                        ? BlobType.MarkDown
                        : BlobType.Text,
                BlobEncoding   = encoding,
                BranchSelector = GetBranchSelectorModel(referenceName, commit.Sha, path),
                PathBar        = new PathBarModel
                {
                    Name          = Name,
                    Action        = "Tree",
                    Path          = path,
                    ReferenceName = referenceName,
                    ReferenceSha  = commit.Sha,
                    HideLastSlash = true,
                },
            };

            return(model);
        }
Example #48
0
 private Blob Downvote(Repository repo)
 {
     return(repo.Lookup <Blob>(repo.Tags[DOWNVOTE].Target.Id));
 }
Example #49
0
        public List <GitCommit> SearchForCommit(MonitoredPathConfig monitoredPathConfig, string monitoredPathName, string sha)
        {
            List <GitCommit> commits = new List <GitCommit>();

            try
            {
                if (string.IsNullOrWhiteSpace(monitoredPathName))
                {
                    monitoredPathName = "default";
                }

                foreach (MonitoredPath mp in monitoredPathConfig.MonitoredPaths)
                {
                    if (string.Compare(mp.Name, monitoredPathName, StringComparison.OrdinalIgnoreCase) == 0 || monitoredPathName == "*")
                    {
                        DirectoryInfo[] directoriesToScan = new DirectoryInfo(mp.Path).GetDirectories("*", SearchOption.TopDirectoryOnly);
                        foreach (DirectoryInfo dir in directoriesToScan)
                        {
                            try
                            {
                                using (Repository repo = new Repository(dir.FullName))
                                {
                                    try
                                    {
                                        Commit com = repo.Lookup <Commit>(sha);
                                        if (com != null)
                                        {
                                            GitRepository gitrepo = new GitRepository();
                                            foreach (var repo1 in mp.Repositories)
                                            {
                                                if (string.Compare(repo1.Name, dir.Name, StringComparison.OrdinalIgnoreCase) == 0)
                                                {
                                                    gitrepo = new GitRepository
                                                    {
                                                        AllowFetch   = repo1.AllowFetch,
                                                        CommitUrl    = repo1.CommitUrl,
                                                        FriendlyName = string.IsNullOrWhiteSpace(repo1.FriendlyName) ? dir.Name : repo1.FriendlyName,
                                                        Name         = dir.Name
                                                    };
                                                }
                                            }

                                            string url           = string.IsNullOrWhiteSpace(gitrepo.CommitUrl) ? string.Empty : string.Format($"{gitrepo.CommitUrl}{com.Sha}");
                                            string repositoryUrl = string.Empty;
                                            if (repo.Network.Remotes?["origin"] != null)
                                            {
                                                repositoryUrl = repo.Network.Remotes["origin"].Url;
                                            }

                                            commits.Add(new GitCommit
                                            {
                                                Author                 = com.Author.Name,
                                                AuthorEmail            = string.IsNullOrWhiteSpace(com.Author.Email) ? string.Empty : com.Author.Email,
                                                AuthorWhen             = com.Author.When.UtcDateTime,
                                                Committer              = com.Committer.Name,
                                                CommitterEmail         = string.IsNullOrWhiteSpace(com.Committer.Email) ? string.Empty : com.Committer.Email,
                                                CommitterWhen          = com.Committer.When.UtcDateTime,
                                                Sha                    = com.Sha,
                                                Message                = com.Message,
                                                RepositoryFriendlyName = gitrepo.FriendlyName,
                                                RepositoryName         = dir.Name,
                                                RepositoryUrl          = repositoryUrl,
                                                CommitUrl              = url,
                                                IsMerge                = com.Parents.Count() > 1
                                            });
                                        }
                                    }
                                    catch
                                    {
                                        // nothing
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                // do nothing
                            }
                        }
                    }
                }

                return(commits);
            }
            catch (Exception ex)
            {
                this.locallogger.LogError("Bad - ", ex);
            }

            return(commits);
        }
Example #50
0
 private Tree EmptyTree(Repository repo)
 {
     return(repo.Lookup <Tree>(repo.Tags[EMPTY_TREE].Target.Id));
 }
Example #51
0
        public TreeEntryModel GetBlob(string path)
        {
            string referenceName;
            var    commit = GetCommitByPath(ref path, out referenceName);

            if (commit == null)
            {
                return(null);
            }

            var entry = commit[path];

            if (entry == null || entry.TargetType != TreeEntryTargetType.Blob)
            {
                return(null);
            }

            var blob = (Blob)entry.Target;

            var lastCommitSha = GitCache.Get <string>(blob.Sha, "affectedcommit");

            if (lastCommitSha == null)
            {
                var hs    = new HashSet <string>();
                var queue = new Queue <Commit>();
                queue.Enqueue(commit);
                hs.Add(commit.Sha);
                while (queue.Count > 0)
                {
                    commit = queue.Dequeue();
                    var has = false;
                    foreach (var parent in commit.Parents)
                    {
                        var tree = parent[path];
                        if (tree == null)
                        {
                            continue;
                        }
                        var eq = tree.Target.Sha == blob.Sha;
                        if (eq && hs.Add(parent.Sha))
                        {
                            queue.Enqueue(parent);
                        }
                        has = has || eq;
                    }
                    if (!has)
                    {
                        break;
                    }
                }
                lastCommitSha = commit.Sha;
                GitCache.Set(blob.Sha, "affectedcommit", lastCommitSha);
            }
            if (lastCommitSha != commit.Sha)
            {
                commit = _repository.Lookup <Commit>(lastCommitSha);
            }

            var data      = blob.GetContentStream().ToBytes();
            var encoding  = FileHelper.DetectEncoding(data, CpToEncoding(commit.Encoding), _i18n.Value);
            var extension = Path.GetExtension(entry.Name).ToLower();
            var model     = new TreeEntryModel
            {
                Name          = entry.Name,
                ReferenceName = referenceName,
                Sha           = commit.Sha,
                Path          = string.IsNullOrEmpty(path) ? "" : path,
                Commit        = new CommitModel
                {
                    Sha                = commit.Sha,
                    Author             = commit.Author,
                    Committer          = commit.Committer,
                    CommitMessage      = commit.Message.RepetitionIfEmpty(NoCommitMessage),
                    CommitMessageShort = commit.MessageShort.RepetitionIfEmpty(NoCommitMessage),
                    Parents            = commit.Parents.Select(s => s.Sha).ToArray()
                },
                EntryType   = entry.TargetType,
                RawData     = data,
                SizeString  = FileHelper.GetSizeString(data.Length),
                TextContent = encoding == null
                    ? null
                    : FileHelper.ReadToEnd(data, encoding),
                TextBrush = FileHelper.BrushMapping.ContainsKey(extension)
                    ? FileHelper.BrushMapping[extension]
                    : "no-highlight",
                BlobType = encoding == null
                    ? FileHelper.ImageSet.Contains(extension)
                        ? BlobType.Image
                        : BlobType.Binary
                    : extension == ".md"
                        ? BlobType.MarkDown
                        : BlobType.Text,
                BlobEncoding   = encoding,
                BranchSelector = GetBranchSelectorModel(referenceName, commit.Sha, path),
                PathBar        = new PathBarModel
                {
                    Name          = Name,
                    Action        = "Tree",
                    Path          = path,
                    ReferenceName = referenceName,
                    ReferenceSha  = commit.Sha,
                    HideLastSlash = true,
                },
            };

            return(model);
        }
Example #52
0
 static bool HandleSingle(string path, string hash)
 {
     using (var repo = new Repository(path))
         return(repo.Lookup <Commit> (hash) != null);
 }
        string TryFindCommit(RepositoryInfoOptions options, Repository r, out Commit commit, out CIBranchVersionMode ciVersionMode, out string branchNameForCIVersion)
        {
            ciVersionMode          = CIBranchVersionMode.None;
            commit                 = null;
            branchNameForCIVersion = null;
            string commitSha = options.StartingCommitSha;

            // Find current commit (the head) if none is provided.
            if (string.IsNullOrWhiteSpace(commitSha))
            {
                IEnumerable <string> branchNames;
                if (string.IsNullOrWhiteSpace(options.StartingBranchName))
                {
                    // locCommit is here because one cannot use an out parameter inside a lambda.
                    var locCommit = commit = r.Head.Tip;
                    if (locCommit == null)
                    {
                        return("Unitialized Git repository.");
                    }
                    // Save the branches!
                    // By doing this, when we are in 'Detached Head' state (the head of the repository is on a commit and not on a branch: git checkout <sha>),
                    // we can detect that it is the head of a branch and hence apply possible options (mainly CI) for it.
                    // We take into account only the branches from options.RemoteName remote here.
                    string branchName = r.Head.FriendlyName;
                    if (branchName == "(no branch)")
                    {
                        string remotePrefix = options.RemoteName + '/';
                        branchNames = r.Branches
                                      .Where(b => b.Tip == locCommit && (!b.IsRemote || b.FriendlyName.StartsWith(remotePrefix)))
                                      .Select(b => b.IsRemote ? b.FriendlyName.Substring(remotePrefix.Length) : b.FriendlyName);
                    }
                    else
                    {
                        branchNames = new[] { branchName }
                    };
                }
                else
                {
                    string remotePrefix    = options.RemoteName + '/';
                    string localBranchName = options.StartingBranchName.StartsWith(remotePrefix)
                                                ? options.StartingBranchName.Substring(remotePrefix.Length)
                                                : options.StartingBranchName;
                    Branch br = r.Branches[options.StartingBranchName];
                    if (br == null && ReferenceEquals(localBranchName, options.StartingBranchName))
                    {
                        string remoteName = remotePrefix + options.StartingBranchName;
                        br = r.Branches[remoteName];
                        if (br == null)
                        {
                            return($"Unknown StartingBranchName: '{options.StartingBranchName}' (also tested on remote '{remoteName}').");
                        }
                    }
                    if (br == null)
                    {
                        return($"Unknown (remote) StartingBranchName: '{options.StartingBranchName}'.");
                    }
                    commit      = br.Tip;
                    branchNames = new[] { localBranchName };
                }
                RepositoryInfoOptionsBranch bOpt;
                if (options.Branches != null &&
                    (bOpt = options.Branches.FirstOrDefault(b => branchNames.Contains(b.Name))) != null &&
                    bOpt.CIVersionMode != CIBranchVersionMode.None)
                {
                    ciVersionMode          = bOpt.CIVersionMode;
                    branchNameForCIVersion = string.IsNullOrWhiteSpace(bOpt.VersionName) ? bOpt.Name : bOpt.VersionName;
                }
            }
            else
            {
                commit = r.Lookup <Commit>(commitSha);
                if (commit == null)
                {
                    return($"Commit '{commitSha}' not found.");
                }
            }
            return(null);
        }
        private void AddCommit(string commitSha)
        {
            var commit = _repository.Lookup(commitSha, GitObjectType.Commit) as Commit;

            AddCommit(commit);
        }
Example #55
0
 /// <summary>
 /// Looks up a commit by an integer that captures the first for bytes of its ID.
 /// </summary>
 /// <param name="repo">The repo to search for a matching commit.</param>
 /// <param name="truncatedId">The value returned from <see cref="GetTruncatedCommitIdAsInt32(Commit)"/>.</param>
 /// <returns>A matching commit.</returns>
 public static Commit GetCommitFromTruncatedIdInteger(this Repository repo, int truncatedId)
 {
     byte[] rawId = BitConverter.GetBytes(truncatedId);
     return(repo.Lookup <Commit>(EncodeAsHex(rawId)));
 }
Example #56
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 #57
0
        public IEnumerable <Change> GetChanges(string since, string extensionFilter)
        {
            using (var repo = new Repository(this.WorkingDirectory))
            {
                var tree     = repo.Head.Tip.Tree;
                var ancestor = repo.Lookup <Commit>(since).Tree;

                using (var changes = repo.Diff.Compare <TreeChanges>(ancestor, tree, extensionFilter.Split()))
                {
                    foreach (var change in changes)
                    {
                        switch (change.Status)
                        {
                        case ChangeKind.Added:
                        {
                            var entry = tree[change.Path];
                            var blob  = (Blob)entry.Target;

                            var contentStream = blob.GetContentStream();
                            using (var tr = new StreamReader(contentStream, Encoding.UTF8))
                            {
                                string content = tr.ReadToEnd();
                                yield return(new Change(GetFilePath(change.Path), "", content, ChangeType.Addition));
                            }
                        }
                        break;

                        case ChangeKind.Modified:
                        {
                            var oldEntry = ancestor[change.OldPath];
                            var newEntry = tree[change.Path];
                            var oldBlob  = (Blob)oldEntry.Target;
                            var newBlob  = (Blob)newEntry.Target;

                            var oldContentStream = oldBlob.GetContentStream();
                            var newContentStream = newBlob.GetContentStream();
                            using (var oldTr = new StreamReader(oldContentStream, Encoding.UTF8))
                                using (var newTr = new StreamReader(newContentStream, Encoding.UTF8))
                                {
                                    string oldContent = oldTr.ReadToEnd();
                                    string newContent = newTr.ReadToEnd();
                                    yield return(new Change(GetFilePath(change.Path), oldContent, newContent, ChangeType.Modification));
                                }
                        }
                        break;

                        case ChangeKind.Deleted:
                        {
                            var entry = ancestor[change.OldPath];
                            var blob  = (Blob)entry.Target;

                            var contentStream = blob.GetContentStream();
                            using (var tr = new StreamReader(contentStream, Encoding.UTF8))
                            {
                                string content = tr.ReadToEnd();
                                yield return(new Change(GetFilePath(change.OldPath), "", content, ChangeType.Deletion));
                            }
                        }
                        break;
                        }
                    }
                }
            }
        }
Example #58
0
        public void StartExternalDiff(ITextDocument textDocument)
        {
            if (textDocument == null || string.IsNullOrEmpty(textDocument.FilePath))
            {
                return;
            }

            var filename = textDocument.FilePath;

            var repositoryPath = GetGitRepository(Path.GetFullPath(filename));

            if (repositoryPath == null)
            {
                return;
            }

            using (var repo = new Repository(repositoryPath))
            {
                string workingDirectory = repo.Info.WorkingDirectory;
                string relativePath     = Path.GetFullPath(filename);
                if (relativePath.StartsWith(workingDirectory, StringComparison.OrdinalIgnoreCase))
                {
                    relativePath = relativePath.Substring(workingDirectory.Length);
                }

                // the name of the object in the database
                string objectName = Path.GetFileName(filename);

                Blob oldBlob    = null;
                var  indexEntry = repo.Index[relativePath];
                if (indexEntry != null)
                {
                    objectName = Path.GetFileName(indexEntry.Path);
                    oldBlob    = repo.Lookup <Blob>(indexEntry.Id);
                }

                var tempFileName = Path.GetTempFileName();
                if (oldBlob != null)
                {
                    File.WriteAllText(tempFileName, oldBlob.GetContentText(new FilteringOptions(relativePath)));
                }

                IVsDifferenceService differenceService = _serviceProvider.GetService(typeof(SVsDifferenceService)) as IVsDifferenceService;
                if (differenceService != null)
                {
                    string leftFileMoniker = tempFileName;
                    // The difference service will automatically load the text from the file open in the editor, even if
                    // it has changed.
                    string rightFileMoniker = filename;

                    string actualFilename = objectName;
                    string tempPrefix     = Path.GetRandomFileName().Substring(0, 5);
                    string caption        = string.Format("{0}_{1} vs. {1}", tempPrefix, actualFilename);

                    string tooltip = null;

                    string leftLabel;
                    if (indexEntry != null)
                    {
                        // determine if the file has been staged
                        string revision;
                        var    stagedMask = FileStatus.NewInIndex | FileStatus.ModifiedInIndex;
                        if ((repo.RetrieveStatus(relativePath) & stagedMask) != 0)
                        {
                            revision = "index";
                        }
                        else
                        {
                            revision = repo.Head.Tip.Sha.Substring(0, 7);
                        }

                        leftLabel = string.Format("{0}@{1}", objectName, revision);
                    }
                    else if (oldBlob != null)
                    {
                        // file was added
                        leftLabel = null;
                    }
                    else
                    {
                        // we just compared to head
                        leftLabel = string.Format("{0}@{1}", objectName, repo.Head.Tip.Sha.Substring(0, 7));
                    }

                    string rightLabel = filename;

                    string inlineLabel = null;
                    string roles       = null;
                    __VSDIFFSERVICEOPTIONS grfDiffOptions = __VSDIFFSERVICEOPTIONS.VSDIFFOPT_LeftFileIsTemporary;
                    differenceService.OpenComparisonWindow2(leftFileMoniker, rightFileMoniker, caption, tooltip, leftLabel, rightLabel, inlineLabel, roles, (uint)grfDiffOptions);

                    // Since the file is marked as temporary, we can delete it now
                    File.Delete(tempFileName);
                }
                else
                {
                    // Can't use __VSDIFFSERVICEOPTIONS, so mark the temporary file(s) read only on disk
                    File.SetAttributes(tempFileName, File.GetAttributes(tempFileName) | FileAttributes.ReadOnly);

                    string remoteFile;
                    if (textDocument.IsDirty)
                    {
                        remoteFile = Path.GetTempFileName();
                        File.WriteAllBytes(remoteFile, GetCompleteContent(textDocument, textDocument.TextBuffer.CurrentSnapshot));
                        File.SetAttributes(remoteFile, File.GetAttributes(remoteFile) | FileAttributes.ReadOnly);
                    }
                    else
                    {
                        remoteFile = filename;
                    }

                    var diffGuiTool = repo.Config.Get <string>("diff.guitool");
                    if (diffGuiTool == null)
                    {
                        diffGuiTool = repo.Config.Get <string>("diff.tool");
                        if (diffGuiTool == null)
                        {
                            return;
                        }
                    }

                    var diffCmd = repo.Config.Get <string>("difftool." + diffGuiTool.Value + ".cmd");
                    if (diffCmd == null || diffCmd.Value == null)
                    {
                        return;
                    }

                    var cmd = diffCmd.Value.Replace("$LOCAL", tempFileName).Replace("$REMOTE", remoteFile);

                    string           fileName  = Regex.Match(cmd, ParameterPattern).Value;
                    string           arguments = cmd.Substring(fileName.Length);
                    ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
                    Process.Start(startInfo);
                }
            }
        }
Example #59
0
        public GitCommitFileSystem Tag(Tag tag)
        {
            var commit = _repo.Lookup <Commit>(tag.Target.Id);

            return(new GitCommitFileSystem(_repo, commit));
        }