From f28886e26d32eaf97180d91dcd42fa045990bdd0 Mon Sep 17 00:00:00 2001 From: Mike Mazur Date: Mon, 16 Mar 2009 00:12:25 +0000 Subject: Rename OpenSim.Framework.Archive to OpenSim.Framework.Serialization Update using statements and prebuild.xml. Also trim trailing whitespace. --- .../Archiver/InventoryArchiveReadRequest.cs | 14 +- .../Archiver/InventoryArchiveWriteRequest.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 2 +- .../World/Archiver/ArchiveReadRequest.cs | 10 +- .../World/Archiver/ArchiveWriteRequestExecution.cs | 26 ++-- .../CoreModules/World/Archiver/AssetsArchiver.cs | 12 +- .../CoreModules/World/Archiver/AssetsDearchiver.cs | 2 +- .../World/Archiver/Tests/ArchiverTests.cs | 154 ++++++++++----------- 8 files changed, 111 insertions(+), 111 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 4ad9974..8dec2c4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -35,7 +35,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.CoreModules.World.Archiver; @@ -208,19 +208,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver failedAssetRestores++; } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) - { + { string fsPath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); // Remove the file portion if we aren't already dealing with a directory path if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) fsPath = fsPath.Remove(fsPath.LastIndexOf("/") + 1); - + string originalFsPath = fsPath; m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to folder {0}", fsPath); InventoryFolderImpl foundFolder = null; - + // XXX: Nasty way of dealing with a path that has no directory component if (fsPath.Length > 0) { @@ -323,15 +323,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { InventoryItemBase item = LoadInvItem(m_asciiEncoding.GetString(data)); - + if (item != null) - { + { // Don't use the item ID that's in the file item.ID = UUID.Random(); item.Creator = m_userInfo.UserProfile.ID; item.Owner = m_userInfo.UserProfile.ID; - + // Reset folder ID to the one in which we want to load it item.Folder = foundFolder.ID; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 364dc28..460fbf5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -34,7 +34,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.CoreModules.World.Archiver; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index ea72f08..bd8d325 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -34,7 +34,7 @@ using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Data; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 69766d4..03e4bce 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -35,7 +35,7 @@ using System.Text; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Interfaces; @@ -52,14 +52,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver private static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - private Scene m_scene; + private Scene m_scene; private Stream m_loadStream; private string m_errorMessage; - + /// /// Should the archive being loaded be merged with what is already on the region? /// - private bool m_merge; + private bool m_merge; /// /// Used to cache lookups for valid uuids. @@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { //m_log.DebugFormat( // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); - + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) { m_log.WarnFormat( diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs index 34332f8..db74564 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs @@ -33,7 +33,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -44,7 +44,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// Method called when all the necessary assets for an archive request have been received. /// public delegate void AssetsRequestCallback(IDictionary assetsFound, ICollection assetsNotFoundUuids); - + /// /// Execute the write of an archive once we have received all the necessary data /// @@ -81,34 +81,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver } m_log.InfoFormat( - "[ARCHIVER]: Received {0} of {1} assets requested", + "[ARCHIVER]: Received {0} of {1} assets requested", assetsFound.Count, assetsFound.Count + assetsNotFoundUuids.Count); - + m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); TarArchiveWriter archive = new TarArchiveWriter(m_saveStream); // Write out control file archive.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile()); - + m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - + // Write out region settings - string settingsPath + string settingsPath = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); archive.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); - + m_log.InfoFormat("[ARCHIVER]: Added region settings to archive."); // Write out terrain - string terrainPath + string terrainPath = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); - + MemoryStream ms = new MemoryStream(); m_terrainModule.SaveToStream(terrainPath, ms); archive.WriteFile(terrainPath, ms.ToArray()); ms.Close(); - + m_log.InfoFormat("[ARCHIVER]: Added terrain information to archive."); // Write out scene object metadata @@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver archive.WriteFile(filename, serializedObject); } - + m_log.InfoFormat("[ARCHIVER]: Added scene objects to archive."); // Write out assets @@ -138,7 +138,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver archive.Close(); m_log.InfoFormat("[ARCHIVER]: Wrote out OpenSimulator archive for {0}", m_scene.RegionInfo.RegionName); - + m_scene.EventManager.TriggerOarFileSaved(String.Empty); } diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs index fb78af9..29d7c5e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs @@ -32,7 +32,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// Post a message to the log every x assets as a progress bar /// private static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50; - + /// /// Archive assets /// @@ -122,7 +122,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar //archive.AddDir("assets"); - + int assetsAdded = 0; foreach (UUID uuid in m_assets.Keys) @@ -145,13 +145,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver archive.WriteFile( ArchiveConstants.ASSETS_PATH + uuid.ToString() + extension, asset.Data); - + assetsAdded++; - + if (assetsAdded % LOG_ASSET_LOAD_NOTIFICATION_INTERVAL == 0) m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", assetsAdded); } - + if (assetsAdded % LOG_ASSET_LOAD_NOTIFICATION_INTERVAL != 0) m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", assetsAdded); } diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs index 67562a9..dae9a93 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs @@ -34,7 +34,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; namespace OpenSim.Region.CoreModules.World.Archiver { diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index f6d0347..6a64ff1 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -34,7 +34,7 @@ using NUnit.Framework; using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Archive; +using OpenSim.Framework.Serialization; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Scenes; @@ -48,29 +48,29 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests private void SaveCompleted(string errorMessage) { lock (this) - { + { System.Console.WriteLine("About to pulse ArchiverTests"); - Monitor.PulseAll(this); - } + Monitor.PulseAll(this); + } } - + /// /// Test saving a V0.2 OpenSim Region Archive. /// - [Test] + [Test] public void TestSaveOarV0p2() - { + { log4net.Config.XmlConfigurator.Configure(); - + ArchiverModule archiverModule = new ArchiverModule(); SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); - + SceneObjectPart part1; - + // Create and add prim 1 { string partName = "My Little Pony"; @@ -79,17 +79,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Vector3 groupPosition = new Vector3(10, 20, 30); Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 + + part1 = new SceneObjectPart( ownerId, shape, groupPosition, rotationOffset, offsetPosition); part1.Name = partName; - + scene.AddNewSceneObject(new SceneObjectGroup(part1), false); } - + SceneObjectPart part2; - + // Create and add prim 2 { string partName = "Action Man"; @@ -98,28 +98,28 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Vector3 groupPosition = new Vector3(90, 80, 70); Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); Vector3 offsetPosition = new Vector3(20, 25, 30); - + part2 = new SceneObjectPart( ownerId, shape, groupPosition, rotationOffset, offsetPosition); part2.Name = partName; - + scene.AddNewSceneObject(new SceneObjectGroup(part2), false); - } - - MemoryStream archiveWriteStream = new MemoryStream(); + } + + MemoryStream archiveWriteStream = new MemoryStream(); scene.EventManager.OnOarFileSaved += SaveCompleted; - + lock (this) { - archiverModule.ArchiveRegion(archiveWriteStream); + archiverModule.ArchiveRegion(archiveWriteStream); Monitor.Wait(this, 60000); - } + } - byte[] archive = archiveWriteStream.ToArray(); + byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - + bool gotControlFile = false; bool gotObject1File = false; bool gotObject2File = false; @@ -132,11 +132,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", part2.Name, Math.Round(part2.GroupPosition.X), Math.Round(part2.GroupPosition.Y), Math.Round(part2.GroupPosition.Z), - part2.UUID); - + part2.UUID); + string filePath; TarArchiveReader.TarEntryType tarEntryType; - + while (tar.ReadEntry(out filePath, out tarEntryType) != null) { if (ArchiveConstants.CONTROL_FILE_PATH == filePath) @@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { string fileName = filePath.Remove(0, ArchiveConstants.OBJECTS_PATH.Length); - + if (fileName.StartsWith(part1.Name)) { Assert.That(fileName, Is.EqualTo(expectedObject1FileName)); @@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests else if (fileName.StartsWith(part2.Name)) { Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); - gotObject2File = true; + gotObject2File = true; } } } @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No object1 file in archive"); Assert.That(gotObject2File, Is.True, "No object2 file in archive"); - + // TODO: Test presence of more files and contents of files. // Temporary Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); @@ -171,143 +171,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests /// /// Test loading a V0.2 OpenSim Region Archive. - /// + /// [Test] public void TestLoadOarV0p2() { //log4net.Config.XmlConfigurator.Configure(); - + MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - + tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); - + string part1Name = "object1"; PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); Vector3 groupPosition = new Vector3(90, 80, 70); Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); Vector3 offsetPosition = new Vector3(20, 25, 30); - + SceneObjectPart part1 = new SceneObjectPart( UUID.Zero, shape, groupPosition, rotationOffset, offsetPosition); part1.Name = part1Name; SceneObjectGroup object1 = new SceneObjectGroup(part1); - + string object1FileName = string.Format( "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", part1Name, Math.Round(groupPosition.X), Math.Round(groupPosition.Y), Math.Round(groupPosition.Z), - part1.UUID); + part1.UUID); tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, object1.ToXmlString2()); - + tar.Close(); - + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - + SerialiserModule serialiserModule = new SerialiserModule(); ArchiverModule archiverModule = new ArchiverModule(); - + Scene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + archiverModule.DearchiveRegion(archiveReadStream); - + SceneObjectPart object1PartLoaded = scene.GetSceneObjectPart(part1Name); - + Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); - Assert.That(object1PartLoaded.Name, Is.EqualTo(part1Name), "object1 names not identical"); + Assert.That(object1PartLoaded.Name, Is.EqualTo(part1Name), "object1 names not identical"); Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(groupPosition), "object1 group position not equal"); Assert.That( object1PartLoaded.RotationOffset, Is.EqualTo(rotationOffset), "object1 rotation offset not equal"); Assert.That( object1PartLoaded.OffsetPosition, Is.EqualTo(offsetPosition), "object1 offset position not equal"); - + // Temporary - Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); + Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } - + /// /// Test merging a V0.2 OpenSim Region Archive into an existing scene - /// + /// ///[Test] public void TestMergeOarV0p2() { //XmlConfigurator.Configure(); - + MemoryStream archiveWriteStream = new MemoryStream(); string part2Name = "objectMerge"; PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder(); Vector3 part2GroupPosition = new Vector3(90, 80, 70); Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90); - Vector3 part2OffsetPosition = new Vector3(20, 25, 30); - + Vector3 part2OffsetPosition = new Vector3(20, 25, 30); + // Create an oar file that we can use for the merge { ArchiverModule archiverModule = new ArchiverModule(); SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); - + SceneObjectPart part2 = new SceneObjectPart( UUID.Zero, part2Shape, part2GroupPosition, part2RotationOffset, part2OffsetPosition); part2.Name = part2Name; SceneObjectGroup object2 = new SceneObjectGroup(part2); - + scene.AddNewSceneObject(object2, false); - + // Write out this scene scene.EventManager.OnOarFileSaved += SaveCompleted; - + lock (this) { - archiverModule.ArchiveRegion(archiveWriteStream); + archiverModule.ArchiveRegion(archiveWriteStream); Monitor.Wait(this, 60000); } } - + { ArchiverModule archiverModule = new ArchiverModule(); SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); - + string part1Name = "objectExisting"; PrimitiveBaseShape part1Shape = PrimitiveBaseShape.CreateCylinder(); Vector3 part1GroupPosition = new Vector3(80, 70, 60); Quaternion part1RotationOffset = new Quaternion(50, 60, 70, 80); Vector3 part1OffsetPosition = new Vector3(15, 20, 25); - + SceneObjectPart part1 = new SceneObjectPart( UUID.Zero, part1Shape, part1GroupPosition, part1RotationOffset, part1OffsetPosition); part1.Name = part1Name; - SceneObjectGroup object1 = new SceneObjectGroup(part1); - + SceneObjectGroup object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); - + // Merge in the archive we created earlier - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + archiverModule.DearchiveRegion(archiveReadStream, true); - - SceneObjectPart object1Existing = scene.GetSceneObjectPart(part1Name); + + SceneObjectPart object1Existing = scene.GetSceneObjectPart(part1Name); Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); - Assert.That(object1Existing.Name, Is.EqualTo(part1Name), "object1 names not identical after merge"); + Assert.That(object1Existing.Name, Is.EqualTo(part1Name), "object1 names not identical after merge"); Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1GroupPosition), "object1 group position not equal after merge"); - + SceneObjectPart object2PartMerged = scene.GetSceneObjectPart(part2Name); Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge"); - Assert.That(object2PartMerged.Name, Is.EqualTo(part2Name), "object2 names not identical after merge"); + Assert.That(object2PartMerged.Name, Is.EqualTo(part2Name), "object2 names not identical after merge"); Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2GroupPosition), "object2 group position not equal after merge"); - } + } } } } -- cgit v1.1