public void CanCopeWithExternalChangesToTheIndex() { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); Touch(scd.DirectoryPath, "a.txt", "a\n"); Touch(scd.DirectoryPath, "b.txt", "b\n"); string path = Repository.Init(scd.DirectoryPath); using (var repoWrite = new Repository(path)) using (var repoRead = new Repository(path)) { var writeStatus = repoWrite.RetrieveStatus(); Assert.True(writeStatus.IsDirty); Assert.Equal(0, repoWrite.Index.Count); var readStatus = repoRead.RetrieveStatus(); Assert.True(readStatus.IsDirty); Assert.Equal(0, repoRead.Index.Count); repoWrite.Stage("*"); repoWrite.Commit("message", Constants.Signature, Constants.Signature); writeStatus = repoWrite.RetrieveStatus(); Assert.False(writeStatus.IsDirty); Assert.Equal(2, repoWrite.Index.Count); readStatus = repoRead.RetrieveStatus(); Assert.False(readStatus.IsDirty); Assert.Equal(2, repoRead.Index.Count); } }
public void StagingANewVersionOfAFileThenUnstagingItRevertsTheBlobToTheVersionOfHead() { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { int count = repo.Index.Count; string filename = Path.Combine("1", "branch_file.txt"); const string posixifiedFileName = "1/branch_file.txt"; ObjectId blobId = repo.Index[posixifiedFileName].Id; string fullpath = Path.Combine(repo.Info.WorkingDirectory, filename); File.AppendAllText(fullpath, "Is there there anybody out there?"); repo.Stage(filename); Assert.Equal(count, repo.Index.Count); Assert.NotEqual((blobId), repo.Index[posixifiedFileName].Id); repo.Unstage(posixifiedFileName); Assert.Equal(count, repo.Index.Count); Assert.Equal(blobId, repo.Index[posixifiedFileName].Id); } }
public void CanGetBlobAsTextWithVariousEncodings(string encodingName, int expectedContentBytes, string expectedUtf7Chars) { var path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var bomFile = "bom.txt"; var content = "1234"; var encoding = Encoding.GetEncoding(encodingName); var bomPath = Touch(repo.Info.WorkingDirectory, bomFile, content, encoding); Assert.Equal(expectedContentBytes, File.ReadAllBytes(bomPath).Length); repo.Stage(bomFile); var commit = repo.Commit("bom", Constants.Signature, Constants.Signature); var blob = (Blob)commit.Tree[bomFile].Target; Assert.Equal(expectedContentBytes, blob.Size); using (var stream = blob.GetContentStream()) { Assert.Equal(expectedContentBytes, stream.Length); } var textDetected = blob.GetContentText(); Assert.Equal(content, textDetected); var text = blob.GetContentText(encoding); Assert.Equal(content, text); var utf7Chars = blob.GetContentText(Encoding.UTF7).Select(c => ((int)c).ToString("X2")).ToArray(); Assert.Equal(expectedUtf7Chars, string.Join(" ", utf7Chars)); } }
public void CommitOnDetachedHeadShouldInsertReflogEntry() { string repoPath = CloneStandardTestRepo(); using (var repo = new Repository(repoPath)) { Assert.False(repo.Info.IsHeadDetached); var parentCommit = repo.Head.Tip.Parents.First(); repo.Checkout(parentCommit.Sha); Assert.True(repo.Info.IsHeadDetached); const string relativeFilepath = "new.txt"; Touch(repo.Info.WorkingDirectory, relativeFilepath, "content\n"); repo.Stage(relativeFilepath); var author = Constants.Signature; const string commitMessage = "Commit on detached head"; var commit = repo.Commit(commitMessage, author, author); // Assert a reflog entry is created on HEAD var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(author, reflogEntry.Commiter); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(string.Format("commit: {0}", commitMessage), repo.Refs.Log("HEAD").First().Message); } }
protected static void AddTag(Repository repo, string tagName) { var randomFile = Path.Combine(repo.Info.WorkingDirectory, Guid.NewGuid().ToString()); File.WriteAllText(randomFile, string.Empty); repo.Stage(randomFile); var sign = SignatureBuilder.SignatureNow(); repo.ApplyTag(tagName, repo.Head.Tip.Id.Sha, sign, "foo"); }
protected static Commit AddOneCommitToHead(Repository repo, string type) { var randomFile = Path.Combine(repo.Info.WorkingDirectory, Guid.NewGuid().ToString()); File.WriteAllText(randomFile, string.Empty); repo.Stage(randomFile); var sign = SignatureBuilder.SignatureNow(); return repo.Commit(type + " commit", sign, sign); }
public void CanDetectedVariousKindsOfRenaming() { string path = InitNewRepository(); using (var repo = new Repository(path)) { Touch(repo.Info.WorkingDirectory, "file.txt", "This is a file with enough data to trigger similarity matching.\r\n" + "This is a file with enough data to trigger similarity matching.\r\n" + "This is a file with enough data to trigger similarity matching.\r\n" + "This is a file with enough data to trigger similarity matching.\r\n"); repo.Stage("file.txt"); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); File.Move(Path.Combine(repo.Info.WorkingDirectory, "file.txt"), Path.Combine(repo.Info.WorkingDirectory, "renamed.txt")); var opts = new StatusOptions { DetectRenamesInIndex = true, DetectRenamesInWorkDir = true }; RepositoryStatus status = repo.RetrieveStatus(opts); // This passes as expected Assert.Equal(FileStatus.RenamedInWorkDir, status.Single().State); repo.Stage("file.txt"); repo.Stage("renamed.txt"); status = repo.RetrieveStatus(opts); Assert.Equal(FileStatus.RenamedInIndex, status.Single().State); File.Move(Path.Combine(repo.Info.WorkingDirectory, "renamed.txt"), Path.Combine(repo.Info.WorkingDirectory, "renamed_again.txt")); status = repo.RetrieveStatus(opts); Assert.Equal(FileStatus.RenamedInWorkDir | FileStatus.RenamedInIndex, status.Single().State); } }
public void CanRemoveAFolderThroughUsageOfPathspecsForNewlyAddedFiles() { string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { repo.Stage(Touch(repo.Info.WorkingDirectory, "2/subdir1/2.txt", "whone")); repo.Stage(Touch(repo.Info.WorkingDirectory, "2/subdir1/3.txt", "too")); repo.Stage(Touch(repo.Info.WorkingDirectory, "2/subdir2/4.txt", "tree")); repo.Stage(Touch(repo.Info.WorkingDirectory, "2/5.txt", "for")); repo.Stage(Touch(repo.Info.WorkingDirectory, "2/6.txt", "fyve")); int count = repo.Index.Count; Assert.True(Directory.Exists(Path.Combine(repo.Info.WorkingDirectory, "2"))); repo.Remove("2", false); Assert.Equal(count - 5, repo.Index.Count); } }
public void StagingAnUnknownFileThrowsIfExplicitPath(string relativePath, FileStatus status) { var path = SandboxStandardTestRepoGitDir(); using (var repo = new Repository(path)) { Assert.Null(repo.Index[relativePath]); Assert.Equal(status, repo.RetrieveStatus(relativePath)); Assert.Throws<UnmatchedPathException>(() => repo.Stage(relativePath, new StageOptions { ExplicitPathsOptions = new ExplicitPathsOptions() })); } }
public void CanLimitStatusToIndexOnly(StatusShowOption show, FileStatus expected) { var clone = SandboxStandardTestRepo(); using (var repo = new Repository(clone)) { Touch(repo.Info.WorkingDirectory, "file.txt", "content"); repo.Stage("file.txt"); RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { Show = show }); Assert.Equal(expected, status["file.txt"].State); } }
public void CanCancelCheckoutThroughNotifyCallback() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { string relativePath = "a.txt"; Touch(repo.Info.WorkingDirectory, relativePath, "Hello\n"); repo.Stage(relativePath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); // Create 2nd branch repo.CreateBranch("branch2"); // Update file in main Touch(repo.Info.WorkingDirectory, relativePath, "Hello from master!\n"); repo.Stage(relativePath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout branch2 repo.Checkout("branch2"); // Update the context of a.txt - a.txt will then conflict between branch2 and master. Touch(repo.Info.WorkingDirectory, relativePath, "Hello From branch2!\n"); // Verify that we get called for the notify conflict cb string conflictPath = string.Empty; CheckoutOptions options = new CheckoutOptions() { OnCheckoutNotify = (path, flags) => { conflictPath = path; return false; }, CheckoutNotifyFlags = CheckoutNotifyFlags.Conflict, }; Assert.Throws<UserCancelledException>(() => repo.Checkout("master", options)); Assert.Equal(relativePath, conflictPath); } }
public void CanStageAnUnknownFileWithLaxUnmatchedExplicitPathsValidation(string relativePath, FileStatus status) { var path = SandboxStandardTestRepoGitDir(); using (var repo = new Repository(path)) { Assert.Null(repo.Index[relativePath]); Assert.Equal(status, repo.RetrieveStatus(relativePath)); Assert.DoesNotThrow(() => repo.Stage(relativePath)); Assert.DoesNotThrow(() => repo.Stage(relativePath, new StageOptions { ExplicitPathsOptions = new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false } })); Assert.Equal(status, repo.RetrieveStatus(relativePath)); } }
public void CanStage(string relativePath, FileStatus currentStatus, bool doesCurrentlyExistInTheIndex, FileStatus expectedStatusOnceStaged, bool doesExistInTheIndexOnceStaged, int expectedIndexCountVariation) { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { int count = repo.Index.Count; Assert.Equal(doesCurrentlyExistInTheIndex, (repo.Index[relativePath] != null)); Assert.Equal(currentStatus, repo.RetrieveStatus(relativePath)); repo.Stage(relativePath); Assert.Equal(count + expectedIndexCountVariation, repo.Index.Count); Assert.Equal(doesExistInTheIndexOnceStaged, (repo.Index[relativePath] != null)); Assert.Equal(expectedStatusOnceStaged, repo.RetrieveStatus(relativePath)); } }
private void AssertPush(Action<IRepository> push) { var scd = BuildSelfCleaningDirectory(); string originalRepoPath = SandboxBareTestRepo(); string clonedRepoPath = Repository.Clone(originalRepoPath, scd.DirectoryPath); using (var originalRepo = new Repository(originalRepoPath)) using (var clonedRepo = new Repository(clonedRepoPath)) { Remote remote = clonedRepo.Network.Remotes["origin"]; // Compare before Assert.Equal(originalRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier, clonedRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier); Assert.Equal( clonedRepo.Network.ListReferences(remote).Single(r => r.CanonicalName == "refs/heads/master"), clonedRepo.Refs.Head.ResolveToDirectReference()); // Change local state (commit) const string relativeFilepath = "new_file.txt"; Touch(clonedRepo.Info.WorkingDirectory, relativeFilepath, "__content__"); clonedRepo.Stage(relativeFilepath); clonedRepo.Commit("__commit_message__", Constants.Signature, Constants.Signature); // Assert local state has changed Assert.NotEqual(originalRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier, clonedRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier); Assert.NotEqual( clonedRepo.Network.ListReferences(remote).Single(r => r.CanonicalName == "refs/heads/master"), clonedRepo.Refs.Head.ResolveToDirectReference()); // Push the change upstream (remote state is supposed to change) push(clonedRepo); // Assert that both local and remote repos are in sync Assert.Equal(originalRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier, clonedRepo.Refs["HEAD"].ResolveToDirectReference().TargetIdentifier); Assert.Equal( clonedRepo.Network.ListReferences(remote).Single(r => r.CanonicalName == "refs/heads/master"), clonedRepo.Refs.Head.ResolveToDirectReference()); } }
public void CanStageAndUnstageAnIgnoredFile() { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { Touch(repo.Info.WorkingDirectory, ".gitignore", "*.ign" + Environment.NewLine); const string relativePath = "Champa.ign"; Touch(repo.Info.WorkingDirectory, relativePath, "On stage!" + Environment.NewLine); Assert.Equal(FileStatus.Ignored, repo.RetrieveStatus(relativePath)); repo.Stage(relativePath, new StageOptions { IncludeIgnored = true }); Assert.Equal(FileStatus.Added, repo.RetrieveStatus(relativePath)); repo.Unstage(relativePath); Assert.Equal(FileStatus.Ignored, repo.RetrieveStatus(relativePath)); } }
public void CanStageTheUpdationOfAStagedFile() { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { int count = repo.Index.Count; const string filename = "new_tracked_file.txt"; IndexEntry blob = repo.Index[filename]; Assert.Equal(FileStatus.Added, repo.RetrieveStatus(filename)); Touch(repo.Info.WorkingDirectory, filename, "brand new content"); Assert.Equal(FileStatus.Added | FileStatus.Modified, repo.RetrieveStatus(filename)); repo.Stage(filename); IndexEntry newBlob = repo.Index[filename]; Assert.Equal(count, repo.Index.Count); Assert.NotEqual(newBlob.Id, blob.Id); Assert.Equal(FileStatus.Added, repo.RetrieveStatus(filename)); } }
public void MergeWithWorkDirConflictsThrows(bool shouldStage, FastForwardStrategy strategy) { // Merging the fast_forward branch results in a change to file // b.txt. In this test we modify the file in the working directory // and then attempt to perform a merge. We expect the merge to fail // due to checkout conflicts. string committishToMerge = "fast_forward"; using (var repo = new Repository(SandboxMergeTestRepo())) { Touch(repo.Info.WorkingDirectory, "b.txt", "this is an alternate change"); if (shouldStage) { repo.Stage("b.txt"); } Assert.Throws <CheckoutConflictException>(() => repo.Merge(committishToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = strategy })); } }
public void CommitShouldCreateReflogEntryOnHeadAndOnTargetedDirectReference() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { // setup refs as HEAD => unit_test => master var newRef = repo.Refs.Add("refs/heads/unit_test", "refs/heads/master"); Assert.NotNull(newRef); repo.Refs.UpdateTarget(repo.Refs.Head, newRef); const string relativeFilepath = "new.txt"; Touch(repo.Info.WorkingDirectory, relativeFilepath, "content\n"); repo.Stage(relativeFilepath); var author = Constants.Signature; const string commitMessage = "Hope reflog behaves as it should"; Commit commit = repo.Commit(commitMessage, author, author); // Assert a reflog entry is created on HEAD Assert.Equal(1, repo.Refs.Log("HEAD").Count()); var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(author, reflogEntry.Commiter); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); // Assert the same reflog entry is created on refs/heads/master Assert.Equal(1, repo.Refs.Log("refs/heads/master").Count()); reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(author, reflogEntry.Commiter); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); // Assert no reflog entry is created on refs/heads/unit_test Assert.Equal(0, repo.Refs.Log("refs/heads/unit_test").Count()); } }
public void CanDetectABinaryDeletion() { using (var repo = new Repository(SandboxStandardTestRepo())) { const string filename = "binfile.foo"; var filepath = Path.Combine(repo.Info.WorkingDirectory, filename); CreateBinaryFile(filepath); repo.Stage(filename); var commit = repo.Commit("Add binary file", Constants.Signature, Constants.Signature); File.Delete(filepath); var patch = repo.Diff.Compare <Patch>(commit.Tree, DiffTargets.WorkingDirectory, new [] { filename }); Assert.True(patch[filename].IsBinaryComparison); repo.Remove(filename); var commit2 = repo.Commit("Delete binary file", Constants.Signature, Constants.Signature); var patch2 = repo.Diff.Compare <Patch>(commit.Tree, commit2.Tree, new[] { filename }); Assert.True(patch2[filename].IsBinaryComparison); } }
/// <summary> /// Commits all changes. /// </summary> /// <param name="message">The message.</param> /// <exception cref="System.Exception"></exception> public bool CommitAllChanges(string message) { try { using (var repo = new Repository(_localFolder.FullName)) { var files = _localFolder.GetFiles("*", SearchOption.AllDirectories).Select(f => f.FullName); repo.Stage(files); //Commands.Stage(repo, _localFolder.FullName); repo.Commit(message); } return(true); } catch (Exception ex) { if (ex.Message.Contains("nothing to commit")) { return(false); } throw; } }
public void CanStageANewFileInAPersistentManner(string filename) { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { Assert.Equal(FileStatus.Nonexistent, repo.RetrieveStatus(filename)); Assert.Null(repo.Index[filename]); Touch(repo.Info.WorkingDirectory, filename, "some contents"); Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(filename)); Assert.Null(repo.Index[filename]); repo.Stage(filename); Assert.NotNull(repo.Index[filename]); Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename)); } using (var repo = new Repository(path)) { Assert.NotNull(repo.Index[filename]); Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename)); } }
public void CanCommitOnBareRepository() { string repoPath = InitNewRepository(true); SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); string workPath = Path.Combine(scd.RootedDirectoryPath, "work"); Directory.CreateDirectory(workPath); var repositoryOptions = new RepositoryOptions { WorkingDirectoryPath = workPath, IndexPath = Path.Combine(scd.RootedDirectoryPath, "index") }; using (var repo = new Repository(repoPath, repositoryOptions)) { const string relativeFilepath = "test.txt"; Touch(repo.Info.WorkingDirectory, relativeFilepath, "test\n"); repo.Stage(relativeFilepath); Assert.NotNull(repo.Commit("Initial commit", Constants.Signature, Constants.Signature)); Assert.Equal(1, repo.Head.Commits.Count()); Assert.Equal(1, repo.Commits.Count()); } }
/// <summary> /// Remove a GPG key from a directory /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void removeToolStripMenuItem_Click(object sender, EventArgs e) { if (listBox1.Items[0].ToString() != Strings.Error_keys_set) { if (listBox1.Items.Count > 1) { listBox1.Items.Remove(listBox1.SelectedItem); listBox1.Refresh(); string tmpFile = Path.GetDirectoryName(frmMain.cfg["PassDirectory"]) + "\\" + treeView1.SelectedNode.FullPath + "\\.gpg-id"; File.Delete(tmpFile); using (StreamWriter w = new StreamWriter(tmpFile)) { foreach (var line in listBox1.Items) { w.WriteLine(line.ToString()); } } using (var repo = new Repository(frmMain.cfg["PassDirectory"])) { repo.Stage(tmpFile); repo.Commit("gpgid changed", new Signature("pass4win", "pass4win", System.DateTimeOffset.Now), new Signature("pass4win", "pass4win", System.DateTimeOffset.Now)); } } } DirectoryInfo path = new DirectoryInfo(Path.GetDirectoryName(frmMain.cfg["PassDirectory"]) + "\\" + treeView1.SelectedNode.FullPath); foreach (var ffile in path.GetFiles()) { if (!ffile.Name.StartsWith(".")) { recrypt(ffile.FullName); } } ScanDirectory(path); }
private static void CommitTest2() { string filename = @"C:\Users\marci\Documents\WebAPI.docx"; using (var repo = new Repository(@"files\folder1")) { // Write content to file system //var content = "Commit this!"; File.Copy(filename, Path.Combine(repo.Info.WorkingDirectory, "webapi.doc")); // File.WriteAllText(Path.Combine(repo.Info.WorkingDirectory, "fileToCommit.txt"), content); // Stage the file repo.Stage("webapi.doc"); // Create the committer's signature and commit Signature author = new Signature("Marcin", "*****@*****.**", DateTime.Now); Signature committer = author; // Commit to the repository Commit commit = repo.Commit("Web API the best!", author, committer); } }
public static void Stage(Repository repository, params string[] paths) { repository.Stage(paths); }
public void CanDetectABinaryChange() { using (var repo = new Repository(SandboxStandardTestRepo())) { const string filename = "binfile.foo"; var filepath = Path.Combine(repo.Info.WorkingDirectory, filename); CreateBinaryFile(filepath); repo.Stage(filename); var commit = repo.Commit("Add binary file", Constants.Signature, Constants.Signature); File.AppendAllText(filepath, "abcdef"); var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename }); Assert.True(patch[filename].IsBinaryComparison); repo.Stage(filename); var commit2 = repo.Commit("Update binary file", Constants.Signature, Constants.Signature); var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename }); Assert.True(patch2[filename].IsBinaryComparison); } }
public void CanDetectTheExactRenamingExactCopyingOfNonModifiedAndModifiedFilesWhenEnabled() { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); var path = Repository.Init(scd.DirectoryPath); using (var repo = new Repository(path)) { const string originalPath = "original.txt"; const string renamedPath = "renamed.txt"; const string originalPath2 = "original2.txt"; const string copiedPath1 = "copied.txt"; const string originalPath3 = "original3.txt"; const string copiedPath2 = "copied2.txt"; Touch(repo.Info.WorkingDirectory, originalPath, "a\nb\nc\nd\n"); Touch(repo.Info.WorkingDirectory, originalPath2, "1\n2\n3\n4\n"); Touch(repo.Info.WorkingDirectory, originalPath3, "5\n6\n7\n8\n"); repo.Stage(originalPath); repo.Stage(originalPath2); repo.Stage(originalPath3); Commit old = repo.Commit("Initial", Constants.Signature, Constants.Signature); var originalFullPath2 = Path.Combine(repo.Info.WorkingDirectory, originalPath2); var originalFullPath3 = Path.Combine(repo.Info.WorkingDirectory, originalPath3); var copiedFullPath1 = Path.Combine(repo.Info.WorkingDirectory, copiedPath1); var copiedFullPath2 = Path.Combine(repo.Info.WorkingDirectory, copiedPath2); File.Copy(originalFullPath2, copiedFullPath1); File.Copy(originalFullPath3, copiedFullPath2); File.AppendAllText(originalFullPath3, "9\n"); repo.Stage(originalPath3); repo.Stage(copiedPath1); repo.Stage(copiedPath2); repo.Move(originalPath, renamedPath); Commit @new = repo.Commit("Updated", Constants.Signature, Constants.Signature); var changes = repo.Diff.Compare<TreeChanges>(old.Tree, @new.Tree, compareOptions: new CompareOptions { Similarity = SimilarityOptions.CopiesHarder, }); Assert.Equal(4, changes.Count()); Assert.Equal(1, changes.Modified.Count()); Assert.Equal(1, changes.Renamed.Count()); Assert.Equal(originalPath, changes.Renamed.Single().OldPath); Assert.Equal(renamedPath, changes.Renamed.Single().Path); Assert.Equal(2, changes.Copied.Count()); Assert.Equal(originalPath2, changes.Copied.ElementAt(0).OldPath); Assert.Equal(copiedPath1, changes.Copied.ElementAt(0).Path); Assert.Equal(originalPath3, changes.Copied.ElementAt(1).OldPath); Assert.Equal(copiedPath2, changes.Copied.ElementAt(1).Path); } }
private void RewriteOutboundLinks() { // for each outbound target file referenced, grab precisely the link from the file and replace it with the new link var outboundLinks = Regex.Matches( File.ReadAllText(repo.Info.WorkingDirectory + targetPattern), @"\[.+?\]\(.+?\)" ); // TODO: what if the links are specified as ref anchors? Then the above regex will not catch them, and they won't be fixed. /* * * Regex.Match( * File.ReadAllText(repo.Info.WorkingDirectory + file.Path), * @"(?<=\]:).+?" + originalFileName * ); * * code for capturing ref anchors * */ StringCollection rewrittenLinks = new StringCollection(); foreach (Match currentOutboundLink in outboundLinks) { string oldOutboundLink = (Regex.Match(currentOutboundLink.Value, @"(?<=\]\().+?(?=\))")).Value; if (rewrittenLinks.Contains(oldOutboundLink)) { continue; } else { rewrittenLinks.Add(oldOutboundLink); } // test code for links: is no op if not testing if (oldOutboundLink.Contains("app-service-logic-enterprise-integration-agreements.md")) { ; } // GetRelativePath takes an absolute path to a file and an absolute path to a directory // and returns the relative path from the latter to the former. // issue: /* * * at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional) * at System.IO.Path.GetFileName(String path) * at CSITools.GitMover.RewriteOutboundLinks() in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\GitMover\GitMover.cs:line 123 * at CSITools.GitMover.Move() in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\GitMover\GitMover.cs:line 101 * at links.MainClass.Main(String[] args) in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\move\Program.cs:line 78 * * * {[Azure Key Vault](../key-vault/key-vault-get-started.md "Learn about Key Vault")} will cause this, which is valid. * * */ // strip any filename out of the entire link. if (oldOutboundLink.IndexOf(' ') != -1) { oldOutboundLink = oldOutboundLink.Remove(oldOutboundLink.IndexOf(' ')); } string targetFileName = ""; try { targetFileName = Path.GetFileName(oldOutboundLink); } catch (Exception ex) { throw ex; } if (targetFileName.StartsWith(@"#") || oldOutboundLink.StartsWith("http")) // link is internal to an H2; no file to rewrite; or external { continue; } var sourceAbsoluteDirectoryPath = (Path.GetDirectoryName(repo.Info.WorkingDirectory + targetPattern) + Path.DirectorySeparatorChar.ToString()).ToAbsoluteDirectoryPath(); // Required: must let the repo go find the target file. An exception will be thrown if it doesn't exist; // POSSIBLE BUG: once we allow files in the repo to be unique only within a directory, it's possible that this will not resolve with only one, // introducing a bug. Only way THEN will be to search for file AND subdirectory. Not doing that now. // NOTE: can't search for complete filename without stripping first any querystrings. string targetFileNameNoQueryStrings = targetFileName; if (targetFileName.IndexOf('?') != -1) { targetFileNameNoQueryStrings = targetFileName.Remove(targetFileName.IndexOf('?')); } if (targetFileName.IndexOf('#') != -1) { targetFileNameNoQueryStrings = targetFileName.Remove(targetFileName.IndexOf('#')); } if (!targetFileNameNoQueryStrings.Contains(".md")) // it's a link, but not to anything we care about { continue; } var targetIndexEntryFromRepo = (from t in repo.Index where t.Path.ToLower().Contains(targetFileNameNoQueryStrings.ToLower()) select t).FirstOrDefault(); if (targetIndexEntryFromRepo == null) { throw new Exception(string.Format("Cannot find file {0}.", targetFileName.ToLower())); } // Now we can construct the absolute path. Could have done this with strings, but.... var targetAbsoluteOutboundLinkPath = (Path.GetDirectoryName(repo.Info.WorkingDirectory + targetIndexEntryFromRepo.Path) + @"\" + targetFileName).ToAbsoluteFilePath(); // var relativeFilePath2 = absoluteFilePath2.GetRelativePathFrom(absoluteDirectoryPath); var test = targetAbsoluteOutboundLinkPath.GetRelativePathFrom(sourceAbsoluteDirectoryPath); string newTargetLink = test.ToString().Replace(@"\", @"/"); if (newTargetLink.StartsWith(@"./")) { newTargetLink = newTargetLink.Remove(0, 2); } string replacementHTML = (File.ReadAllText(repo.Info.WorkingDirectory + targetPattern)) .Replace(oldOutboundLink, newTargetLink.ToLower()); // go back to linux links: //replacementHTML = replacementHTML.Replace(@"\", @"/"); File.WriteAllText(repo.Info.WorkingDirectory + targetPattern, replacementHTML); repo.Stage(repo.Info.WorkingDirectory + targetPattern); } }
public void CheckoutUpdatesModifiedFilesInWorkingDirectory() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); // Modify file in master branch. // Verify contents match initial commit after checking out other branch. string fullPath = Touch( repo.Info.WorkingDirectory, originalFilePath, "Update : hello from master branch!\n"); repo.Stage(fullPath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout other_branch Branch otherBranch = repo.Branches[otherBranchName]; Assert.NotNull(otherBranch); otherBranch.Checkout(); // Verify working directory is updated Assert.False(repo.RetrieveStatus().IsDirty); Assert.Equal(originalFileContent, File.ReadAllText(fullPath)); } }
public void CheckoutRemovesExtraFilesInWorkingDirectory() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); // Add extra file in master branch // Verify it is removed after checking out otherBranch. string newFileFullPath = Touch( repo.Info.WorkingDirectory, "b.txt", "hello from master branch!\n"); repo.Stage(newFileFullPath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout other_branch Branch otherBranch = repo.Branches[otherBranchName]; Assert.NotNull(otherBranch); otherBranch.Checkout(); // Verify working directory is updated Assert.False(repo.RetrieveStatus().IsDirty); Assert.False(File.Exists(newFileFullPath)); } }
public void CheckingOutWithMergeConflictsThrows() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello\n"); repo.Stage(originalFilePath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); // Create 2nd branch repo.CreateBranch("branch2"); // Update file in main Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello from master!\n"); repo.Stage(originalFilePath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout branch2 repo.Checkout("branch2"); Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello From branch2!\n"); // Assert that checking out master throws // when there are unstaged commits Assert.Throws<MergeConflictException>(() => repo.Checkout("master")); // And when there are staged commits repo.Stage(originalFilePath); Assert.Throws<MergeConflictException>(() => repo.Checkout("master")); } }
public void CanForcefullyCheckoutWithConflictingStagedChanges() { // This test will check that we can checkout a branch that results // in a conflict. Here is the high level steps of the test: // 1) Create branch otherBranch from current commit in master, // 2) Commit change to master // 3) Switch to otherBranch // 4) Create conflicting change // 5) Forcefully checkout master string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { Branch master = repo.Branches["master"]; Assert.True(master.IsCurrentRepositoryHead); // Set the working directory to the current head. ResetAndCleanWorkingDirectory(repo); Assert.False(repo.RetrieveStatus().IsDirty); // Create otherBranch from current Head. repo.Branches.Add(otherBranchName, master.Tip); // Add change to master. Touch(repo.Info.WorkingDirectory, originalFilePath, originalFileContent); repo.Stage(originalFilePath); repo.Commit("change in master", Constants.Signature, Constants.Signature); // Checkout otherBranch. repo.Checkout(otherBranchName); // Add change to otherBranch. Touch(repo.Info.WorkingDirectory, originalFilePath, alternateFileContent); repo.Stage(originalFilePath); // Assert that normal checkout throws exception // for the conflict. Assert.Throws<MergeConflictException>(() => repo.Checkout(master.CanonicalName)); // Checkout with force option should succeed. repo.Checkout(master.CanonicalName, new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force}); // Assert that master branch is checked out. Assert.True(repo.Branches["master"].IsCurrentRepositoryHead); // And that the current index is not dirty. Assert.False(repo.RetrieveStatus().IsDirty); } }
private void RewriteOutboundLinks() { // for each outbound target file referenced, grab precisely the link from the file and replace it with the new link var outboundLinks = Regex.Matches( File.ReadAllText(repo.Info.WorkingDirectory + targetPattern), @"(?<=\]):{0,1}.+?.md" // above is the newline: // @"\[.+?\]\(.+?\)" ); // TODO: what if the links are specified as ref anchors? Then the above regex will not catch them, and they won't be fixed. /* * * Regex.Match( * File.ReadAllText(repo.Info.WorkingDirectory + file.Path), * @"(?<=\]:).+?" + originalFileName * ); * * code for capturing ref anchors * * (?<=\]:).+?.md * * then, strip off the filename with Path.GetFilename and search for that. * * capture all links: (?<=\]):{0,1}.+?.md leaving online : or ( in front, so strip that out and continue normally. * */ StringCollection rewrittenLinks = new StringCollection(); foreach (Match currentOutboundLink in outboundLinks) { if (currentOutboundLink.Value.Contains("cli-install-nodejs.md")) { ; } // old regex: "(?<=\]\().+?(?=\))" ==> current regex also catches reference anchors. string oldOutboundLink = (Regex.Match(currentOutboundLink.Value, @"(?<=[:\(]).*")).Value; if (oldOutboundLink.StartsWith(":") || oldOutboundLink.StartsWith("(")) { throw new Exception("well, THAT didn't work, now, did it?"); } if (rewrittenLinks.Contains(oldOutboundLink)) { continue; } else { rewrittenLinks.Add(oldOutboundLink); } // test code for links: is no op if not testing if (oldOutboundLink.Contains("app-service-logic-enterprise-integration-agreements.md")) { ; } // GetRelativePath takes an absolute path to a file and an absolute path to a directory // and returns the relative path from the latter to the former. // issue: /* * * at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional) * at System.IO.Path.GetFileName(String path) * at CSITools.GitMover.RewriteOutboundLinks() in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\GitMover\GitMover.cs:line 123 * at CSITools.GitMover.Move() in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\GitMover\GitMover.cs:line 101 * at links.MainClass.Main(String[] args) in C:\Users\rasquill\Documents\GitHub\gitwork\dotnet\move\move\Program.cs:line 78 * * * {[Azure Key Vault](../key-vault/key-vault-get-started.md "Learn about Key Vault")} will cause this, which is valid. * * */ // strip any filename out of the entire link. // first, capture the querystring, if any string queryString = string.Empty; if (oldOutboundLink.Contains("?")) { queryString = oldOutboundLink.Substring(oldOutboundLink.IndexOf("?")); } // second, handle the removal of extraneous markdown goo oldOutboundLink = CleanURL(oldOutboundLink); // Ignore some links if (oldOutboundLink.StartsWith("http")) // link is internal to an H2; no file to rewrite; or external { continue; } if (!oldOutboundLink.Contains(".md")) // it's a link, but not to anything we care about { continue; } string targetFileName = ""; try { targetFileName = Path.GetFileName(oldOutboundLink); } catch (Exception ex) { throw ex; } // handle the case where someone specified the "this" file name if (targetFileName.Equals(Path.GetFileName(sourcePattern))) { targetFileName = Path.GetFileName(targetPattern); targetFileName = CleanURL(targetFileName); oldOutboundLink = oldOutboundLink.Replace(Path.GetFileName(sourcePattern), targetFileName); } var sourceAbsoluteDirectoryPath = (Path.GetDirectoryName(repo.Info.WorkingDirectory + targetPattern) + Path.DirectorySeparatorChar.ToString()).ToAbsoluteDirectoryPath(); // TODO: need to search for all files to find the one that matches exactly, rather than assume the first one is correct. /* * first, take the link and see if it exists in the file system. If it does, don't go looking any further and use that value. * if it does not exist in the system, THEN go looking for PRECISELY the filename, and take a guess. There could be sixteen * "add-disk.md" files, and no way to decide if the original link was incorrect, so just take the first one and go. * IN ADDITION: found file must NOT be a redirect file, which is an easy way of making a mistake. */ IndexEntry targetIndexEntryFromRepo; // if the file can be found on the file system and is NOT a redirect file, use that. // OK: a. Find out if there's more than one file. // b. if there's two files, choose the one that is not a redirect file. // c. if there's more, check the -c value and either throw or write to console. You can't guess. /* * var repoFileHits = from t in repo.Index where t.Path.ToLower().Contains(targetFileName.ToLower()) select t; * * if (repoFileHits.Count() == 1) * { * // this is assumed to be the file. * // detect redirect and retarget using THAT file name to scuttle the redirect. * } * else if (repoFileHits.Count() == 2) * { * // one of these is likely a redirect. if so, use the other one. * } * else if (repoFileHits.Count() > 2) * { * // just take the first one if you can; but in all cases write out the situation and say you're going to guess * // throw an exception if -c is not specified, otherwise continue. * } */ // TODO: Here the problem is that if the targetfilename has been reset to the new name (in a recursivelink) // you're trying to find that file with the previous file name, which sets you on the wrong path. :-| // above, you should IF it's a recursive link, just reset oldOutboundLink to "this file" target pattern, I think. if (File.Exists(Path.Combine(sourceAbsoluteDirectoryPath.ToString(), oldOutboundLink))) { if (Regex.IsMatch(File.ReadAllText(Path.Combine(sourceAbsoluteDirectoryPath.ToString(), oldOutboundLink)), "redirect_url:")) { // here extract and use the redirect value string redirectlink = Regex.Match(currentOutboundLink.Value, @"(?<=redirect_url: /azure/).+?").Value; targetIndexEntryFromRepo = (from t in repo.Index where t.Path.ToLower().Contains(redirectlink.ToLower()) select t) .FirstOrDefault(); } else { targetIndexEntryFromRepo = (from t in repo.Index where t.Path.ToLower().Contains(targetFileName.ToLower()) select t) .FirstOrDefault(); } } else // if the file IS either a redirect file OR the full path can't be found, search by file NAME and then retest for redirection. { // Console.WriteLine($"Cannot locate the outbound target \"{oldOutboundLink}\" as a file; trying the filename in the repo."); var tempRepoHits = (from t in repo.Index where t.Path.ToLower().Contains(@"\" + targetFileName.ToLower()) select t); if (tempRepoHits != null && tempRepoHits.Count() == 1) { targetIndexEntryFromRepo = tempRepoHits.First(); } // what if it's tWO? Gotta find the one that is NOT a redirect else if (tempRepoHits != null && tempRepoHits.Count() == 2) { if (Regex.IsMatch(File.ReadAllText(repo.Info.WorkingDirectory + tempRepoHits.First().Path), "redirect_url:")) { // here extract and use the redirect value string redirectlink = Regex.Match(File.ReadAllText(repo.Info.WorkingDirectory + tempRepoHits.First().Path), @"(?<=redirect_url: /azure/).*").Value; if (redirectlink.EndsWith("\r")) { redirectlink = redirectlink.Remove(redirectlink.Length - 1); } redirectlink = redirectlink.Replace(@"/", @"\"); // on Windows, repo responds with windows separators. targetIndexEntryFromRepo = (from t in repo.Index where t.Path.ToLower().Contains(redirectlink.ToLower() + ".md") select t) .FirstOrDefault(); } else { //take the other one targetIndexEntryFromRepo = tempRepoHits.ElementAt(1); } } else // hey, just can't have confidence we know which one it might be. { targetIndexEntryFromRepo = null; } } if (targetIndexEntryFromRepo == null) { if (this.ignoreNonFatalErrors) { Console.WriteLine($"Relinking file and cannot find linked file {targetFileName.ToLower()} or there are more than two possibilities."); continue; } else { throw new Exception($"Cannot find file {targetFileName.ToLower()}."); } } // Now we can construct the absolute path. Could have done this with strings, but.... var targetAbsoluteOutboundLinkPath = (Path.GetDirectoryName(repo.Info.WorkingDirectory + targetIndexEntryFromRepo.Path) + @"\" + targetFileName).ToAbsoluteFilePath(); // var relativeFilePath2 = absoluteFilePath2.GetRelativePathFrom(absoluteDirectoryPath); var test = targetAbsoluteOutboundLinkPath.GetRelativePathFrom(sourceAbsoluteDirectoryPath); string newTargetLink = test.ToString().Replace(@"\", @"/"); if (newTargetLink.StartsWith(@"./")) { newTargetLink = newTargetLink.Remove(0, 2); } string replacementHTML = (File.ReadAllText(repo.Info.WorkingDirectory + targetPattern)) .Replace(oldOutboundLink, newTargetLink.ToLower()); // go back to linux links: //replacementHTML = replacementHTML.Replace(@"\", @"/"); File.WriteAllText(repo.Info.WorkingDirectory + targetPattern, replacementHTML); repo.Stage(repo.Info.WorkingDirectory + targetPattern); } }
private static void DeleteFile(Repository repo, string fileName) { File.Delete(Path.Combine(repo.Info.WorkingDirectory, fileName)); repo.Stage(fileName); repo.Commit("remove file", Constants.Signature, Constants.Signature); }
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))); repo.Stage(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."); } }
public void CanLookupWhithShortIdentifers() { const string expectedAbbrevSha = "fe8410b"; const string expectedSha = expectedAbbrevSha + "6bfdf69ccfd4f397110d61f8070e46e40"; string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { const string filename = "new.txt"; Touch(repo.Info.WorkingDirectory, filename, "one "); repo.Stage(filename); Signature author = Constants.Signature; Commit commit = repo.Commit("Initial commit", author, author); Assert.Equal(expectedSha, commit.Sha); GitObject lookedUp1 = repo.Lookup(expectedSha); Assert.Equal(commit, lookedUp1); GitObject lookedUp2 = repo.Lookup(expectedAbbrevSha); Assert.Equal(commit, lookedUp2); } }
private void ConstructRebaseTestRepository(Repository repo, string attributes = "* text=auto", string lineEnding = "\r\n") { // Constructs a graph that looks like: // * -- * -- * (modifications to c.txt) // / | // / T2 // / // * -- * -- * (modifications to b.txt) // / | // / T1 // / // *--*--*--*--*--*---- // | | \ // M1 M2 \ // ---* // | // C1 const string fileContentA1 = "A1"; const string fileContentB1 = "B1"; const string fileContentB2 = "B2"; const string fileContentB3 = "B3"; const string fileContentB4 = "B4"; const string fileContentC1 = "C1"; const string fileContentC2 = "C2"; const string fileContentC3 = "C3"; const string fileContentC4 = "C4"; const string fileContentD1 = "D1"; const string fileContentD2 = "D2"; const string fileContentD3 = "D3"; string workdir = repo.Info.WorkingDirectory; Commit commit = null; CreateAttributesFile(repo, attributes); repo.Stage(".gitattributes"); commit = repo.Commit("setup", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathA, fileContentA1); repo.Stage(filePathA); commit = repo.Commit("commit 1", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, fileContentB1); repo.Stage(filePathB); commit = repo.Commit("commit 2", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, fileContentC1); repo.Stage(filePathC); commit = repo.Commit("commit 3", Constants.Signature, Constants.Signature, new CommitOptions()); Branch masterBranch1 = repo.CreateBranch(masterBranch1Name, commit); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2)); repo.Stage(filePathB); commit = repo.Commit("commit 4", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3)); repo.Stage(filePathB); commit = repo.Commit("commit 5", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3, fileContentB4)); repo.Stage(filePathB); commit = repo.Commit("commit 6", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(topicBranch1Name, commit); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2)); repo.Stage(filePathC); commit = repo.Commit("commit 7", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3)); repo.Stage(filePathC); commit = repo.Commit("commit 8", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3, fileContentC4)); repo.Stage(filePathC); commit = repo.Commit("commit 9", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(topicBranch2Name, commit); repo.Checkout(masterBranch1.Tip); Touch(workdir, filePathD, fileContentD1); repo.Stage(filePathD); commit = repo.Commit("commit 10", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2)); repo.Stage(filePathD); commit = repo.Commit("commit 11", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2, fileContentD3)); repo.Stage(filePathD); commit = repo.Commit("commit 12", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(masterBranch2Name, commit); // Create commit / branch that conflicts with T1 and T2 Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2 + fileContentB3 + fileContentB4)); repo.Stage(filePathB); commit = repo.Commit("commit 13", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(conflictBranch1Name, commit); }
public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory) { if (isDirectory) { expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar; } string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); string relativePathUpdated = "updated.txt"; Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A"); repo.Stage(relativePathUpdated); repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature); // Create conflicting change string relativePathConflict = "conflict.txt"; Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A"); repo.Stage(relativePathConflict); repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature); // Create another branch repo.CreateBranch("newbranch"); // Make an edit to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature); // Checkout other branch repo.Checkout("newbranch"); // Make alternate edits to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature); // make conflicting change to conflict.txt Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD"); repo.Stage(relativePathConflict); // Create ignored change string relativePathIgnore = Path.Combine("bin", "ignored.txt"); Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file"); // Create untracked change string relativePathUntracked = "untracked.txt"; Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file"); bool wasCalled = false; string actualNotificationPath = string.Empty; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; CheckoutOptions options = new CheckoutOptions() { OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return true; }, CheckoutNotifyFlags = notifyFlags, }; Assert.Throws<MergeConflictException>(() => repo.Checkout("master", options)); Assert.True(wasCalled); Assert.Equal(expectedNotificationPath, actualNotificationPath); Assert.Equal(notifyFlags, actualNotifyFlags); } }
public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory) { if (isDirectory) { expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar; } string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); const string relativePathUpdated = "updated.txt"; Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A"); repo.Stage(relativePathUpdated); repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature); // Create conflicting change const string relativePathConflict = "conflict.txt"; Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A"); repo.Stage(relativePathConflict); repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature); // Create another branch repo.CreateBranch("newbranch"); // Make an edit to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature); // Checkout other branch repo.Checkout("newbranch"); // Make alternate edits to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature); // make conflicting change to conflict.txt Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD"); repo.Stage(relativePathConflict); // Create ignored change string relativePathIgnore = Path.Combine("bin", "ignored.txt"); Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file"); // Create untracked change const string relativePathUntracked = "untracked.txt"; Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file"); bool wasCalled = false; string actualNotificationPath = string.Empty; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; CheckoutOptions options = new CheckoutOptions() { OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return(true); }, CheckoutNotifyFlags = notifyFlags, }; Assert.Throws <CheckoutConflictException>(() => repo.Checkout("master", options)); Assert.True(wasCalled); Assert.Equal(expectedNotificationPath, actualNotificationPath); Assert.Equal(notifyFlags, actualNotifyFlags); } }
public void CheckoutBranchSnapshot() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); // Get the current status of master // and the current tip. Branch initial = repo.Branches["master"]; Commit initialCommit = initial.Tip; // Add commit to master string fullPath = Touch(repo.Info.WorkingDirectory, originalFilePath, "Update : hello from master branch!\n"); repo.Stage(fullPath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); Assert.False(repo.Info.IsHeadDetached); initial.Checkout(); // Head should point at initial commit. Assert.Equal(repo.Head.Tip, initialCommit); Assert.False(repo.RetrieveStatus().IsDirty); // Verify that HEAD is detached. Assert.Equal(repo.Refs["HEAD"].TargetIdentifier, initial.Tip.Sha); Assert.True(repo.Info.IsHeadDetached); } }
public void Stage(IEnumerable <string> stageFiles) { repo.Stage(stageFiles); }
public void CheckoutRetainsStagedChanges() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); // Generate a staged change. string fullPathFileA = Touch(repo.Info.WorkingDirectory, originalFilePath, alternateFileContent); repo.Stage(fullPathFileA); // Verify that there is a staged entry. Assert.Equal(1, repo.RetrieveStatus().Staged.Count()); Assert.Equal(FileStatus.Staged, repo.RetrieveStatus(fullPathFileA)); repo.Checkout(otherBranchName); // Verify staged entry still exists. Assert.Equal(1, repo.RetrieveStatus().Staged.Count()); Assert.Equal(FileStatus.Staged, repo.RetrieveStatus(fullPathFileA)); } }
public void CanCommitALittleBit() { string repoPath = InitNewRepository(); var identity = Constants.Identity; using (var repo = new Repository(repoPath, new RepositoryOptions { Identity = identity })) { string dir = repo.Info.Path; Assert.True(Path.IsPathRooted(dir)); Assert.True(Directory.Exists(dir)); const string relativeFilepath = "new.txt"; string filePath = Touch(repo.Info.WorkingDirectory, relativeFilepath, "null"); repo.Stage(relativeFilepath); File.AppendAllText(filePath, "token\n"); repo.Stage(relativeFilepath); Assert.Null(repo.Head[relativeFilepath]); var author = Constants.Signature; const string shortMessage = "Initial egotistic commit"; const string commitMessage = shortMessage + "\n\nOnly the coolest commits from us"; var before = DateTimeOffset.Now.TruncateMilliseconds(); Commit commit = repo.Commit(commitMessage, author, author); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n"); AssertBlobContent(commit[relativeFilepath], "nulltoken\n"); Assert.Equal(0, commit.Parents.Count()); Assert.False(repo.Info.IsHeadUnborn); // Assert a reflog entry is created on HEAD Assert.Equal(1, repo.Refs.Log("HEAD").Count()); var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); var now = DateTimeOffset.Now; Assert.InRange(reflogEntry.Committer.When, before, now); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); Assert.Equal(string.Format("commit (initial): {0}", shortMessage), reflogEntry.Message); // Assert a reflog entry is created on HEAD target var targetCanonicalName = repo.Refs.Head.TargetIdentifier; Assert.Equal(1, repo.Refs.Log(targetCanonicalName).Count()); Assert.Equal(commit.Id, repo.Refs.Log(targetCanonicalName).First().To); File.WriteAllText(filePath, "nulltoken commits!\n"); repo.Stage(relativeFilepath); var author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5)); Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n"); AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n"); Assert.Equal(1, commit2.Parents.Count()); Assert.Equal(commit.Id, commit2.Parents.First().Id); // Assert the reflog is shifted Assert.Equal(2, repo.Refs.Log("HEAD").Count()); Assert.Equal(reflogEntry.To, repo.Refs.Log("HEAD").First().From); Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit); repo.Checkout(firstCommitBranch); File.WriteAllText(filePath, "davidfowl commits!\n"); var author3 = new Signature("David Fowler", "*****@*****.**", author.When.AddSeconds(2)); repo.Stage(relativeFilepath); Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3); AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n"); AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n"); Assert.Equal(1, commit3.Parents.Count()); Assert.Equal(commit.Id, commit3.Parents.First().Id); AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n"); } }
public void CanStageAFileGeneratedFromABlobContentStream() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { for (int i = 0; i < 5; i++) { var sb = new StringBuilder(); for (int j = 0; j < 2000; j++) { sb.Append(((i + 1)*(j + 1)).ToString("X8")); } File.AppendAllText(Path.Combine(repo.Info.WorkingDirectory, "small.txt"), sb.ToString()); } repo.Stage("small.txt"); IndexEntry entry = repo.Index["small.txt"]; Assert.Equal("baae1fb3760a73481ced1fa03dc15614142c19ef", entry.Id.Sha); var blob = repo.Lookup<Blob>(entry.Id.Sha); using (Stream stream = blob.GetContentStream()) using (Stream file = File.OpenWrite(Path.Combine(repo.Info.WorkingDirectory, "small.fromblob.txt"))) { CopyStream(stream, file); } repo.Stage("small.fromblob.txt"); IndexEntry newentry = repo.Index["small.fromblob.txt"]; Assert.Equal("baae1fb3760a73481ced1fa03dc15614142c19ef", newentry.Id.Sha); } }
public void CanIncludeUnmodifiedEntriesWhenEnabled() { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); var path = Repository.Init(scd.DirectoryPath); using (var repo = new Repository(path)) { Touch(repo.Info.WorkingDirectory, "a.txt", "abc\ndef\n"); Touch(repo.Info.WorkingDirectory, "b.txt", "abc\ndef\n"); repo.Stage(new[] {"a.txt", "b.txt"}); Commit old = repo.Commit("Initial", Constants.Signature, Constants.Signature); File.AppendAllText(Path.Combine(repo.Info.WorkingDirectory, "b.txt"), "ghi\njkl\n"); repo.Stage("b.txt"); Commit @new = repo.Commit("Updated", Constants.Signature, Constants.Signature); var changes = repo.Diff.Compare<TreeChanges>(old.Tree, @new.Tree, compareOptions: new CompareOptions {IncludeUnmodified = true}); Assert.Equal(2, changes.Count()); Assert.Equal(1, changes.Unmodified.Count()); Assert.Equal(1, changes.Modified.Count()); } }
public void CanFilterLargeFiles() { const int ContentLength = 128 * 1024 * 1024 - 13; const char ContentValue = 'x'; char[] content = (new string(ContentValue, 1024)).ToCharArray(); string repoPath = InitNewRepository(); var filter = new FileExportFilter(FilterName, attributes); var registration = GlobalSettings.RegisterFilter(filter); try { string filePath = Path.Combine(Directory.GetParent(repoPath).Parent.FullName, Guid.NewGuid().ToString() + ".blob"); FileInfo contentFile = new FileInfo(filePath); using (var writer = new StreamWriter(contentFile.OpenWrite()) { AutoFlush = true }) { int remain = ContentLength; while (remain > 0) { int chunkSize = remain > content.Length ? content.Length : remain; writer.Write(content, 0, chunkSize); remain -= chunkSize; } } string attributesPath = Path.Combine(Directory.GetParent(repoPath).Parent.FullName, ".gitattributes"); FileInfo attributesFile = new FileInfo(attributesPath); string configPath = CreateConfigurationWithDummyUser(Constants.Identity); var repositoryOptions = new RepositoryOptions { GlobalConfigurationLocation = configPath }; using (Repository repo = new Repository(repoPath, repositoryOptions)) { File.WriteAllText(attributesPath, "*.blob filter=test"); repo.Stage(attributesFile.Name); repo.Stage(contentFile.Name); repo.Commit("test", Constants.Signature, Constants.Signature); contentFile.Delete(); repo.Checkout("HEAD", new CheckoutOptions() { CheckoutModifiers = CheckoutModifiers.Force }); } contentFile = new FileInfo(filePath); Assert.True(contentFile.Exists, "Contents not restored correctly by forced checkout."); using (StreamReader reader = contentFile.OpenText()) { int totalRead = 0; char[] block = new char[1024]; int read; while ((read = reader.Read(block, 0, block.Length)) > 0) { Assert.True(CharArrayAreEqual(block, content, read)); totalRead += read; } Assert.Equal(ContentLength, totalRead); } contentFile.Delete(); } finally { GlobalSettings.DeregisterFilter(registration); } }
public static void Stage(Repository repository, IEnumerable <string> paths) { repository.Stage(paths); }
public async void Stage(FileStatusViewModel change) { repository.Stage(change.Path); await LoadWorkingDirectoryStatusAsync(); }
public static bool PublishToGit(string remoteGitPath, string localGitPath, string userName, string passWord) { //TODO: This function may throw exception, should I catch them and return false? //init Repository.Init(localGitPath); Repository repo = new Repository(localGitPath); string nameKey = "user.name"; string emailKey = "user.email"; string name = repo.Config.GetValueOrDefault(nameKey, (string)null); if (name == null) { name = userName; repo.Config.Set(nameKey, name); } string email = repo.Config.GetValueOrDefault(emailKey, (string)null); if (email == null) { email = userName + "@" + Environment.MachineName; repo.Config.Set(emailKey, email); } //stage & commit repo.Stage("*"); try { repo.Commit("Auto-generated by PublishDoc"); } catch (Exception e) { if (e is LibGit2Sharp.EmptyCommitException) { Console.WriteLine("Warning! Empty commit!"); } else { throw e; } } //set remote Remote remote = repo.Network.Remotes["origin"]; if (remote == null) { repo.Network.Remotes.Add("origin", remoteGitPath); remote = repo.Network.Remotes["origin"]; } else { repo.Network.Remotes.Update(remote, r => r.Url = remoteGitPath); } //force push string pushRefSpec = string.Format("+{0}:{0}", repo.Head.CanonicalName); var pushOptions = new PushOptions() { CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials { Username = userName, Password = passWord } }; repo.Network.Push(remote, pushRefSpec, pushOptions); return(true); }