public void Sync_FileLockedForWritingDuringUpdate_GetUpdatedFileOnceLockIsGone() { HgRunner.TimeoutSecondsOverrideForUnitTests = 3; using (var bob = new RepositorySetup("bob")) { bob.ProjectFolderConfig.IncludePatterns.Add("*.txt"); bob.AddAndCheckinFile("one.txt", "hello"); using (var sally = new RepositorySetup("sally", bob)) { bob.AddAndCheckinFile("one.txt", "hello-bob"); using (sally.GetFileLockForWriting("one.txt")) { // Note: Mono succeeds here Assert.That(sally.CheckinAndPullAndMerge(bob).Succeeded, Is.False, "CheckinAndPullAndMerge should have failed"); sally.AssertFileContents("one.txt", "hello"); } sally.AssertSingleHead(); //ok, now whatever was holding that file is done with it, and we try again Assert.That(sally.CheckinAndPullAndMerge(bob).Succeeded, Is.True, "ChecinAndPullAndMerge(bob) should have succeeded"); sally.AssertFileContents("one.txt", "hello-bob"); } } }
public void FileDeletedLocallyAndChangedRemotelyKeepsChanged() { using (var localRepo = new RepositorySetup("unbundleTests")) { var localFilePath = localRepo.ProjectFolder.GetNewTempFile(true).Path; localRepo.AddAndCheckinFile(localFilePath, "file to change and delete"); using (var remoteRepo = new RepositorySetup("remote", localRepo)) { remoteRepo.CheckinAndPullAndMerge(); var remoteFilePath = Path.Combine(remoteRepo.ProjectFolder.Path, Path.GetFileName(localFilePath)); Assert.That(File.Exists(remoteFilePath)); // Make sure that we have a file to delete. File.Delete(remoteFilePath); remoteRepo.SyncWithOptions(new SyncOptions { CheckinDescription = "delete file", DoMergeWithOthers = false, DoPullFromOthers = false, DoSendToOthers = false }); Assert.That(!File.Exists(remoteFilePath)); // Make sure we actually got rid of it. localRepo.ChangeFileAndCommit(localFilePath, "new file contents", "changed the file"); localRepo.CheckinAndPullAndMerge(remoteRepo); Assert.That(File.Exists(localFilePath), Is.True, "Did not keep changed file."); var chorusNotesPath = localFilePath + ".ChorusNotes"; Assert.That(File.Exists(chorusNotesPath), "Did not record conflict"); AssertThatXmlIn.File(chorusNotesPath).HasAtLeastOneMatchForXpath("//annotation[@class='mergeconflict']"); } } }
public void SynchNow_OnNamedBranchAndDefaultBranchExists_DoesNotMergeWithIt() { using (var repo = new RepositorySetup("bob")) { if (repo.Synchronizer == null) { repo.Synchronizer = repo.CreateSynchronizer(); } repo.Synchronizer.SynchronizerAdjunct = new ProgrammableSynchronizerAdjunct("default"); repo.AddAndCheckinFile("test.txt", "apple"); var afterFirstCheckin = repo.CreateBookmarkHere(); repo.ChangeFileAndCommit("test.txt", "pear", "second on default"); afterFirstCheckin.Go(); repo.Repository.BranchingHelper.Branch(new ConsoleProgress(), "animals"); repo.Synchronizer.SynchronizerAdjunct = new ProgrammableSynchronizerAdjunct("animals"); repo.ChangeFileAndCommit("test.txt", "dog", "first on animals"); var animalHead = repo.CreateBookmarkHere(); repo.AssertHeadCount(2); repo.CheckinAndPullAndMerge(); repo.AssertHeadCount(2); animalHead.AssertRepoIsAtThisPoint(); } }
public void Sync_FirstCheckInButNoFilesAdded_NoProblem() { using (var bob = new RepositorySetup("bob")) { var result = bob.CheckinAndPullAndMerge(); Assert.That(result.Succeeded, Is.True, result.ErrorEncountered?.Message); } }
public void Sync_HgrcInUseByOther_FailsGracefully() { HgRunner.TimeoutSecondsOverrideForUnitTests = 1; using (var setup = new RepositorySetup("bob")) { using (new StreamWriter(setup.ProjectFolder.Combine(".hg", "hgrc"))) { var results = setup.CheckinAndPullAndMerge(); Assert.IsFalse(results.Succeeded); } } }
public void Sync_HgrcInUseByOther_FailsGracefully() { HgRunner.TimeoutSecondsOverrideForUnitTests = 1; using (var setup = new RepositorySetup("bob")) { using (var stream = new FileStream(setup.ProjectFolder.Combine(".hg", "hgrc"), FileMode.Create, FileAccess.Write, FileShare.None)) using (new StreamWriter(stream)) { var results = setup.CheckinAndPullAndMerge(); Assert.That(results.Succeeded, Is.False); } } }
public void SynchNow_OnDefaultBranchAndAnotherBranchExists_DoesNotMergeWithIt() { using (var repo = new RepositorySetup("bob")) { repo.AddAndCheckinFile("test.txt", "hello"); repo.AssertHeadCount(1); repo.ChangeFileOnNamedBranchAndComeBack("test.txt", "blah", "mybranch"); //NB: this used to pass prior to hg 1.5, but, well, it shouldn't! // Shouldn't there be two heads after the branch, above? (jh, April 2010) // repo.AssertHeadCount(1); repo.ChangeFileAndCommit("test.txt", "hello there", "second"); repo.AssertHeadCount(2); repo.CheckinAndPullAndMerge(); repo.AssertHeadCount(2); } }
public void Sync_ExistingRejectChangeSet_NotMergedIn() { using (var bob = new RepositorySetup("bob")) { bob.AddAndCheckinFile("test.txt", "original"); bob.CreateRejectForkAndComeBack(); bob.ChangeFileAndCommit("test.txt", "ok", "goodGuy"); //move on so we have two distinct branches bob.AssertHeadCount(2); bob.CheckinAndPullAndMerge(null); Assert.AreEqual("goodGuy", bob.Repository.GetRevisionWorkingSetIsBasedOn().Summary); bob.AssertLocalRevisionNumber(3); bob.AssertHeadCount(2); } }
public void Sync_FileLockedForReadingDuringMerge_LeftWithMultipleHeads() { HgRunner.TimeoutSecondsOverrideForUnitTests = 3; using (var bob = new RepositorySetup("bob")) { bob.ProjectFolderConfig.IncludePatterns.Add("*.txt"); bob.AddAndCheckinFile("one.txt", "hello"); using (var sally = new RepositorySetup("sally", bob)) { bob.AddAndCheckinFile("one.txt", "hello-bob"); using (sally.GetFileLockForReading("one.txt")) { sally.CheckinAndPullAndMerge(bob); } sally.AssertHeadCount(2); } } }
public void ChangedUtf8File_FileCanBePulledAndUpdated() { using (var setup = new RepositorySetup("Dan")) { const string utf8FilePath = "açesbsun.wav"; setup.ChangeFile(utf8FilePath, "hello1"); setup.ProjectFolderConfig.IncludePatterns.Add("*.wav"); setup.AddAndCheckIn(); using (var other = new RepositorySetup("Bob", setup)) { setup.ChangeFile(utf8FilePath, "hello2"); setup.Repository.Commit(false, "update"); other.CheckinAndPullAndMerge(setup); // Fix: Currently this modifies Dan adding bogus file unexpectedly. other.AssertFileExists(utf8FilePath); string[] fileNames = Directory.GetFiles(other.ProjectFolder.Path, "*.wav"); Assert.AreEqual(1, fileNames.Length); } } }
public void Sync_MergeFailure_NoneOfTheOtherGuysFilesMakeItIntoWorkingDirectory() { using (var bob = new RepositorySetup("bob")) { bob.ProjectFolderConfig.IncludePatterns.Add("*.txt"); bob.AddAndCheckinFile("aaa.txt", "apple"); bob.AddAndCheckinFile("bbb.txt", "bread"); bob.AddAndCheckinFile("zzz.txt", "zoo"); using (var sally = new RepositorySetup("sally", bob)) { bob.AddAndCheckinFile("aaa.txt", "bob-apple"); bob.AddAndCheckinFile("bbb.txt", "bob-bread"); bob.AddAndCheckinFile("zzz.txt", "bob-zoo"); using (new FailureSimulator("TextMerger-bbb.txt")) { sally.AddAndCheckinFile("aaa.txt", "sally-apple"); sally.AddAndCheckinFile("bbb.txt", "sally-bread"); sally.AddAndCheckinFile("zzz.txt", "sally-zipper"); Assert.That(sally.CheckinAndPullAndMerge(bob).Succeeded, Is.False); //make sure we ended up on Sally's revision, even though Bob's are newer var currentRevision = sally.Repository.GetRevisionWorkingSetIsBasedOn(); Assert.AreEqual("sally", sally.Repository.GetRevision(currentRevision.Number.Hash).UserId); //sally should see no changes, because it should all be rolled back sally.AssertFileContents("aaa.txt", "sally-apple"); sally.AssertFileContents("bbb.txt", "sally-bread"); sally.AssertFileContents("zzz.txt", "sally-zipper"); // sally.ShowInTortoise(); sally.AssertHeadCount(2); Assert.That(sally.GetProgressString(), Does.Not.Contain("creates new remote heads")); } } } File.Delete(Path.Combine(Path.GetTempPath(), "TextMerger-bbb.txt")); }
public void Sync_ModifiedFileIsInvalid_CheckedInButThenBackedOut() { /* * @ changeset: 2 | summary: [Backout due to validation Failure] | | o changeset: 1 | summary: missing checkin description | | o changeset: 0 | summary: Add test.chorusTest */ using (var bob = new RepositorySetup("bob")) { bob.AddAndCheckinFile("test.chorusTest", "original"); bob.AssertLocalRevisionNumber(0); bob.ChangeFile("test.chorusTest", ChorusTestFileHandler.GetInvalidContents()); bob.CheckinAndPullAndMerge(); bob.AssertLocalRevisionNumber(2); bob.AssertHeadCount(1); bob.AssertLocalRevisionNumber(int.Parse(bob.Repository.GetTip().Number.LocalRevisionNumber)); Debug.WriteLine(bob.Repository.GetLog(-1)); } }
[Category("UnknownMonoIssue")] // Do3WayMerge is never called on Mono, for some reason. public void DictConfigMerge_DifferentUpradePathKeepsFileFormat() { const string commonAncestor = null; const string sue = @"<?xml version='1.0' encoding='utf-8'?> <DictionaryConfiguration name='Root-based (complex forms as subentries)' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' allPublications='true' version='14' lastModified='2014-10-07'> <ConfigurationItem name='Main Entry' style='Dictionary-Normal' isEnabled='true' field='LexEntry' cssClassNameOverride='entry'> <ParagraphOptions paragraphStyle='Dictionary-Normal' continuationParagraphStyle='Dictionary-Continuation' /> <ConfigurationItem name='Headword' between=' ' after=' ' style='Dictionary-Headword' isEnabled='true' field='MLHeadWord' cssClassNameOverride='mainheadword'> <WritingSystemOptions writingSystemType='vernacular' displayWSAbreviation='false'> <Option id='vernacular' isEnabled='false'/> <Option id='fr' isEnabled='true' /> </WritingSystemOptions> </ConfigurationItem> <ConfigurationItem name='Variant Forms' before='(' between='; ' after=') ' isEnabled='true' field='VariantFormEntryBackRefs'> <ListTypeOptions list='variant'> <Option isEnabled='true' id='b0000000-c40e-433e-80b5-31da08771344'/> <Option isEnabled='false' id='0c4663b3-4d9a-47af-b9a1-c8565d8112ed'/> </ListTypeOptions> </ConfigurationItem> </ConfigurationItem> </DictionaryConfiguration>"; const string randy = @"<?xml version='1.0' encoding='utf-8'?> <DictionaryConfiguration xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' name='Root-based (complex forms as subentries)' allPublications='true' version='17' lastModified='2014-10-07'> <ConfigurationItem name='Main Entry' style='Dictionary-Normal' isEnabled='true' field='LexEntry' cssClassNameOverride='entry'> <ParagraphOptions paragraphStyle='Dictionary-Normal' continuationParagraphStyle='Dictionary-Continuation' /> <ConfigurationItem name='Headword' between=' ' after=' ' style='Dictionary-Headword' isEnabled='true' field='MLHeadWord' cssClassNameOverride='mainheadword'> <WritingSystemOptions writingSystemType='vernacular' displayWSAbreviation='false'> <Option id='vernacular' isEnabled='true'/> </WritingSystemOptions> </ConfigurationItem> <ConfigurationItem name='Variant Forms' before='(' between='; ' after=') ' isEnabled='true' field='VariantFormEntryBackRefs'> <ListTypeOptions list='variant'> <Option isEnabled='false' id='b0000000-c40e-433e-80b5-31da08771344'/> <Option isEnabled='true' id='0c4663b3-4d9a-47af-b9a1-c8565d8112ed'/> </ListTypeOptions> </ConfigurationItem> </ConfigurationItem> </DictionaryConfiguration>"; using (var tempFolder = new TemporaryFolder("Temp")) { // Copy the Dictionary Configuration Schema to where the Dictionary Configuration Handler Strategy looks var appsDir = Path.GetDirectoryName(Utilities.StripFilePrefix(Assembly.GetExecutingAssembly().CodeBase)); var xsdPath = Path.Combine(appsDir, "TestData", "Language Explorer", "Configuration", SharedConstants.DictConfigSchemaFilename); var xsdPathInProj = Path.Combine(tempFolder.Path, SharedConstants.DictConfigSchemaFilename); File.Copy(xsdPath, xsdPathInProj, true); using (var sueRepo = new RepositorySetup("Sue", true)) { sueRepo.AddAndCheckinFile("unrelated.txt", "unrelated to SUT, here to get us rev 0 so repos are related"); using (var randyRepo = new RepositorySetup("Randy", sueRepo)) { // By doing the clone before making Sue's changes, we get the common starting state in both repos. sueRepo.AddAndCheckinFile(string.Format("root.{0}", SharedConstants.fwdictconfig), sue); var randyDictConfigInRepoPath = Path.Combine(randyRepo.ProjectFolder.Path, string.Format("root.{0}", SharedConstants.fwdictconfig)); var mergeConflictsNotesFile = ChorusNotesMergeEventListener.GetChorusNotesFilePath(randyDictConfigInRepoPath); Assert.IsFalse(File.Exists(mergeConflictsNotesFile), "ChorusNotes file should NOT have been in working set."); randyRepo.AddAndCheckinFile(string.Format("root.{0}", SharedConstants.fwdictconfig), randy); randyRepo.CheckinAndPullAndMerge(sueRepo); Assert.IsTrue(File.Exists(mergeConflictsNotesFile), "ChorusNotes file should have been in working set."); var notesContents = File.ReadAllText(mergeConflictsNotesFile); Assert.IsNotNullOrEmpty(notesContents); Assert.That(notesContents, Is.StringContaining("Both added the same element, but with different content")); Assert.That(notesContents, Is.StringContaining("The merger kept the change made by Randy.")); Assert.That(notesContents, Is.StringContaining("alphaUserId=\"Randy\"")); Assert.That(notesContents, Is.StringContaining("betaUserId=\"Sue\"")); // Make sure merged file has Randy's changes var doc = XDocument.Load(randyDictConfigInRepoPath); var options = doc.Root.Element("ConfigurationItem").Elements("ConfigurationItem").Last(/*Variant Forms*/) .Element("ListTypeOptions").Elements("Option").ToList(); Assert.AreEqual(2, options.Count, "There should be two Variant Forms options"); Assert.AreEqual("b0000000-c40e-433e-80b5-31da08771344", options[0].Attribute("id").Value, "Options are out of order"); Assert.AreEqual("0c4663b3-4d9a-47af-b9a1-c8565d8112ed", options[1].Attribute("id").Value, "Options are out of order"); Assert.AreEqual("false", options[0].Attribute("isEnabled").Value, "First option should be disabled"); Assert.AreEqual("true", options[1].Attribute("isEnabled").Value, "Second option should be enabled"); // Make sure merged file does *not* have Sue's changes options = doc.Root.Element("ConfigurationItem").Element("ConfigurationItem" /*Headword*/) .Element("WritingSystemOptions").Elements("Option").ToList(); Assert.AreEqual(1, options.Count, "There should be only one WS Option"); Assert.AreEqual("vernacular", options[0].Attribute("id").Value, "should be default vernacular"); Assert.AreEqual("true", options[0].Attribute("isEnabled").Value, "should be enabled"); // Make sure the merged file has proper xsd namespace attributes var xsiAttr = doc.Root.Attribute("xsi"); var xsdAttr = doc.Root.Attribute("xsd"); Assert.Null(xsiAttr, "xsi missing namespace"); Assert.Null(xsdAttr, "xsd missing namespace"); // XNamespace xsiNs = "http://www.w3.org/2001/XMLSchema-instance"; XNamespace xsdNs = "http://www.w3.org/2001/XMLSchema"; xsiAttr = doc.Root.Attribute(xsiNs + "xsi"); xsdAttr = doc.Root.Attribute(xsdNs + "xsd"); Assert.Null(xsiAttr, "xsi attribute missing entirely from result"); Assert.Null(xsdAttr, "xsd attribute missing entirely from result"); } } } }