Add --merge switch to load iar.
When this switch is used, iar folders are merged with existing same-name user inventory folders. This makes it a little easier to back and restore entire individual user inventories, among other things Added unit test to check behaviourprebuild-update
							parent
							
								
									be0af01061
								
							
						
					
					
						commit
						5925aac859
					
				| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using OpenMetaverse;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Framework.Serialization
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +172,30 @@ namespace OpenSim.Framework.Serialization
 | 
			
		|||
        public static string CreateOarObjectPath(string objectName, UUID uuid, Vector3 pos)
 | 
			
		||||
        {
 | 
			
		||||
            return OBJECTS_PATH + CreateOarObjectFilename(objectName, uuid, pos);          
 | 
			
		||||
        }        
 | 
			
		||||
        }  
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Extract a plain path from an IAR path
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="iarPath"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static string ExtractPlainPathFromIarPath(string iarPath)
 | 
			
		||||
        {
 | 
			
		||||
            List<string> plainDirs = new List<string>();
 | 
			
		||||
 | 
			
		||||
            string[] iarDirs = iarPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
            
 | 
			
		||||
            foreach (string iarDir in iarDirs)
 | 
			
		||||
            {
 | 
			
		||||
                if (!iarDir.Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
 | 
			
		||||
                    plainDirs.Add(iarDir);
 | 
			
		||||
                
 | 
			
		||||
                int i = iarDir.LastIndexOf(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
 | 
			
		||||
 | 
			
		||||
                plainDirs.Add(iarDir.Remove(i));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            return string.Join("/", plainDirs.ToArray());          
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +54,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
 | 
			
		||||
        private UserAccount m_userInfo;
 | 
			
		||||
        private string m_invPath;
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Do we want to merge this load with existing inventory?
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected bool m_merge;
 | 
			
		||||
 | 
			
		||||
        /// <value>
 | 
			
		||||
        /// We only use this to request modules
 | 
			
		||||
| 
						 | 
				
			
			@ -66,19 +71,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        private Stream m_loadStream;
 | 
			
		||||
 | 
			
		||||
        public InventoryArchiveReadRequest(
 | 
			
		||||
            Scene scene, UserAccount userInfo, string invPath, string loadPath)
 | 
			
		||||
            Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge)
 | 
			
		||||
            : this(
 | 
			
		||||
                scene,
 | 
			
		||||
                userInfo,
 | 
			
		||||
                invPath,
 | 
			
		||||
                new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress))
 | 
			
		||||
                new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
 | 
			
		||||
                merge)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public InventoryArchiveReadRequest(
 | 
			
		||||
            Scene scene, UserAccount userInfo, string invPath, Stream loadStream)
 | 
			
		||||
            Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
 | 
			
		||||
        {
 | 
			
		||||
            m_scene = scene;
 | 
			
		||||
            m_merge = merge;
 | 
			
		||||
            m_userInfo = userInfo;
 | 
			
		||||
            m_invPath = invPath;
 | 
			
		||||
            m_loadStream = loadStream;
 | 
			
		||||
| 
						 | 
				
			
			@ -91,14 +98,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
 | 
			
		||||
        /// returned
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public List<InventoryNodeBase> Execute()
 | 
			
		||||
        public HashSet<InventoryNodeBase> Execute()
 | 
			
		||||
        {
 | 
			
		||||
            string filePath = "ERROR";
 | 
			
		||||
            int successfulAssetRestores = 0;
 | 
			
		||||
            int failedAssetRestores = 0;
 | 
			
		||||
            int successfulItemRestores = 0;
 | 
			
		||||
            
 | 
			
		||||
            List<InventoryNodeBase> loadedNodes = new List<InventoryNodeBase>();
 | 
			
		||||
            HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>();
 | 
			
		||||
           
 | 
			
		||||
            List<InventoryFolderBase> folderCandidates
 | 
			
		||||
                = InventoryArchiveUtils.FindFolderByPath(
 | 
			
		||||
| 
						 | 
				
			
			@ -158,9 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
                            {
 | 
			
		||||
                                successfulItemRestores++;
 | 
			
		||||
                                
 | 
			
		||||
                                // If we're loading an item directly into the given destination folder then we need to record
 | 
			
		||||
                                // it separately from any loaded root folders
 | 
			
		||||
                                if (rootDestinationFolder == foundFolder)
 | 
			
		||||
                                // If we aren't loading the folder containing the item then well need to update the 
 | 
			
		||||
                                // viewer separately for that item.
 | 
			
		||||
                                if (!loadedNodes.Contains(foundFolder))
 | 
			
		||||
                                    loadedNodes.Add(item);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			@ -203,14 +210,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
            string iarPath, 
 | 
			
		||||
            InventoryFolderBase rootDestFolder, 
 | 
			
		||||
            Dictionary <string, InventoryFolderBase> resolvedFolders,
 | 
			
		||||
            List<InventoryNodeBase> loadedNodes)
 | 
			
		||||
            HashSet<InventoryNodeBase> loadedNodes)
 | 
			
		||||
        {
 | 
			
		||||
            string iarPathExisting = iarPath;
 | 
			
		||||
 | 
			
		||||
//            m_log.DebugFormat(
 | 
			
		||||
//                "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
 | 
			
		||||
                        
 | 
			
		||||
            InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
 | 
			
		||||
            InventoryFolderBase destFolder 
 | 
			
		||||
                = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
 | 
			
		||||
            
 | 
			
		||||
            m_log.DebugFormat(
 | 
			
		||||
                "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", 
 | 
			
		||||
| 
						 | 
				
			
			@ -249,46 +257,55 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        {                       
 | 
			
		||||
            string originalArchivePath = archivePath;
 | 
			
		||||
 | 
			
		||||
            InventoryFolderBase destFolder = null;
 | 
			
		||||
 | 
			
		||||
            if (archivePath.Length > 0)
 | 
			
		||||
            while (archivePath.Length > 0)
 | 
			
		||||
            {
 | 
			
		||||
                while (null == destFolder && archivePath.Length > 0)
 | 
			
		||||
                m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
 | 
			
		||||
                
 | 
			
		||||
                if (resolvedFolders.ContainsKey(archivePath))
 | 
			
		||||
                {
 | 
			
		||||
                    m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
 | 
			
		||||
                    
 | 
			
		||||
                    if (resolvedFolders.ContainsKey(archivePath))
 | 
			
		||||
                    m_log.DebugFormat(
 | 
			
		||||
                        "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
 | 
			
		||||
                    return resolvedFolders[archivePath];
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if (m_merge)
 | 
			
		||||
                    {
 | 
			
		||||
                        m_log.DebugFormat(
 | 
			
		||||
                            "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
 | 
			
		||||
                        destFolder = resolvedFolders[archivePath];
 | 
			
		||||
                        // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the 
 | 
			
		||||
                        // iar name and try to find that instead.
 | 
			
		||||
                        string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
 | 
			
		||||
                        List<InventoryFolderBase> folderCandidates
 | 
			
		||||
                            = InventoryArchiveUtils.FindFolderByPath(
 | 
			
		||||
                                m_scene.InventoryService, m_userInfo.PrincipalID, plainPath);
 | 
			
		||||
            
 | 
			
		||||
                        if (folderCandidates.Count != 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            InventoryFolderBase destFolder = folderCandidates[0];
 | 
			
		||||
                            resolvedFolders[archivePath] = destFolder;
 | 
			
		||||
                            return destFolder;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    // Don't include the last slash so find the penultimate one
 | 
			
		||||
                    int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
 | 
			
		||||
 | 
			
		||||
                    if (penultimateSlashIndex >= 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Remove the last section of path so that we can see if we've already resolved the parent
 | 
			
		||||
                        archivePath = archivePath.Remove(penultimateSlashIndex + 1);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // Don't include the last slash so find the penultimate one
 | 
			
		||||
                        int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
 | 
			
		||||
 | 
			
		||||
                        if (penultimateSlashIndex >= 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            // Remove the last section of path so that we can see if we've already resolved the parent
 | 
			
		||||
                            archivePath = archivePath.Remove(penultimateSlashIndex + 1);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            m_log.DebugFormat(
 | 
			
		||||
                                "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
 | 
			
		||||
                                originalArchivePath);
 | 
			
		||||
                            archivePath = string.Empty;
 | 
			
		||||
                            destFolder = rootDestFolder;
 | 
			
		||||
                        }
 | 
			
		||||
                        m_log.DebugFormat(
 | 
			
		||||
                            "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
 | 
			
		||||
                            originalArchivePath);
 | 
			
		||||
                        archivePath = string.Empty;
 | 
			
		||||
                        return rootDestFolder;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if (null == destFolder)
 | 
			
		||||
                destFolder = rootDestFolder;
 | 
			
		||||
            
 | 
			
		||||
            return destFolder;
 | 
			
		||||
            return rootDestFolder;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -314,24 +331,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
            string iarPathExisting,
 | 
			
		||||
            string iarPathToReplicate, 
 | 
			
		||||
            Dictionary <string, InventoryFolderBase> resolvedFolders, 
 | 
			
		||||
            List<InventoryNodeBase> loadedNodes)
 | 
			
		||||
            HashSet<InventoryNodeBase> loadedNodes)
 | 
			
		||||
        {
 | 
			
		||||
            string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
            int i = 0;
 | 
			
		||||
 | 
			
		||||
            while (i < rawDirsToCreate.Length)
 | 
			
		||||
            for (int i = 0; i < rawDirsToCreate.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
//                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
 | 
			
		||||
 | 
			
		||||
                if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
 | 
			
		||||
                    continue;
 | 
			
		||||
                
 | 
			
		||||
                int identicalNameIdentifierIndex
 | 
			
		||||
                    = rawDirsToCreate[i].LastIndexOf(
 | 
			
		||||
                        ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
 | 
			
		||||
 | 
			
		||||
                if (identicalNameIdentifierIndex < 0)
 | 
			
		||||
                {
 | 
			
		||||
                    i++;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
 | 
			
		||||
 | 
			
		||||
                newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
 | 
			
		||||
| 
						 | 
				
			
			@ -354,8 +368,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
 | 
			
		||||
                if (0 == i)
 | 
			
		||||
                    loadedNodes.Add(destFolder);
 | 
			
		||||
 | 
			
		||||
                i++;
 | 
			
		||||
            }            
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,12 +91,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
                
 | 
			
		||||
                scene.AddCommand(
 | 
			
		||||
                    this, "load iar",
 | 
			
		||||
					"load iar <first> <last> <inventory path> <password> [<IAR path>]",				                 
 | 
			
		||||
                    "load iar <first> <last> <inventory path> <password> [<IAR path>]",                              
 | 
			
		||||
                    //"load iar [--merge] <first> <last> <inventory path> <password> [<IAR path>]",
 | 
			
		||||
                    "Load user inventory archive (IAR).",
 | 
			
		||||
				    //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones"
 | 
			
		||||
                    //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones"
 | 
			
		||||
                    //+ "<first> is user's first name." + Environment.NewLine
 | 
			
		||||
                    "<first> is user's first name." + Environment.NewLine				                 
 | 
			
		||||
                    "<first> is user's first name." + Environment.NewLine                                
 | 
			
		||||
                    + "<last> is user's last name." + Environment.NewLine
 | 
			
		||||
                    + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine
 | 
			
		||||
                    + "<password> is the user's password." + Environment.NewLine
 | 
			
		||||
| 
						 | 
				
			
			@ -136,16 +136,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
            if (handlerInventoryArchiveSaved != null)
 | 
			
		||||
                handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
 | 
			
		||||
        }
 | 
			
		||||
		
 | 
			
		||||
        
 | 
			
		||||
        public bool ArchiveInventory(
 | 
			
		||||
		     Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
 | 
			
		||||
		{
 | 
			
		||||
			return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>());
 | 
			
		||||
		}
 | 
			
		||||
             Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
 | 
			
		||||
        {
 | 
			
		||||
            return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ArchiveInventory(
 | 
			
		||||
		    Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 
 | 
			
		||||
		    Dictionary<string, object> options)
 | 
			
		||||
            Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 
 | 
			
		||||
            Dictionary<string, object> options)
 | 
			
		||||
        {
 | 
			
		||||
            if (m_scenes.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -184,8 +184,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        }
 | 
			
		||||
                        
 | 
			
		||||
        public bool ArchiveInventory(
 | 
			
		||||
		    Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 
 | 
			
		||||
		    Dictionary<string, object> options)
 | 
			
		||||
            Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 
 | 
			
		||||
            Dictionary<string, object> options)
 | 
			
		||||
        {
 | 
			
		||||
            if (m_scenes.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -224,13 +224,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream)
 | 
			
		||||
		{
 | 
			
		||||
			return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
        {
 | 
			
		||||
            return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public bool DearchiveInventory(
 | 
			
		||||
		    string firstName, string lastName, string invPath, string pass, Stream loadStream, 
 | 
			
		||||
		    Dictionary<string, object> options)
 | 
			
		||||
            string firstName, string lastName, string invPath, string pass, Stream loadStream, 
 | 
			
		||||
            Dictionary<string, object> options)
 | 
			
		||||
        {
 | 
			
		||||
            if (m_scenes.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -241,10 +241,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
                    if (CheckPresence(userInfo.PrincipalID))
 | 
			
		||||
                    {
 | 
			
		||||
                        InventoryArchiveReadRequest request;
 | 
			
		||||
                        bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);                        
 | 
			
		||||
                        
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream);
 | 
			
		||||
                            request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (EntryPointNotFoundException e)
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			@ -273,8 +274,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        public bool DearchiveInventory(
 | 
			
		||||
		     string firstName, string lastName, string invPath, string pass, string loadPath, 
 | 
			
		||||
		     Dictionary<string, object> options)
 | 
			
		||||
             string firstName, string lastName, string invPath, string pass, string loadPath, 
 | 
			
		||||
             Dictionary<string, object> options)
 | 
			
		||||
        {
 | 
			
		||||
            if (m_scenes.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -285,10 +286,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
                    if (CheckPresence(userInfo.PrincipalID))
 | 
			
		||||
                    {
 | 
			
		||||
                        InventoryArchiveReadRequest request;
 | 
			
		||||
                        bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);                        
 | 
			
		||||
                        
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath);
 | 
			
		||||
                        {                            
 | 
			
		||||
                            request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (EntryPointNotFoundException e)
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			@ -322,13 +324,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        /// <param name="cmdparams"></param>
 | 
			
		||||
        protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams)
 | 
			
		||||
        {
 | 
			
		||||
			m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL.  BUG REPORTS WELCOME.");			
 | 
			
		||||
			
 | 
			
		||||
			Dictionary<string, object> options = new Dictionary<string, object>();            
 | 
			
		||||
            m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL.  BUG REPORTS WELCOME.");          
 | 
			
		||||
            
 | 
			
		||||
            Dictionary<string, object> options = new Dictionary<string, object>();            
 | 
			
		||||
            OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
 | 
			
		||||
            
 | 
			
		||||
            List<string> mainParams = optionSet.Parse(cmdparams);
 | 
			
		||||
			
 | 
			
		||||
            
 | 
			
		||||
            if (mainParams.Count < 6)
 | 
			
		||||
            {
 | 
			
		||||
                m_log.Error(
 | 
			
		||||
| 
						 | 
				
			
			@ -349,7 +351,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
            if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options))
 | 
			
		||||
                m_log.InfoFormat(
 | 
			
		||||
                    "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}",
 | 
			
		||||
                    loadPath, firstName, lastName);				
 | 
			
		||||
                    loadPath, firstName, lastName);             
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +456,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
 | 
			
		|||
        /// Notify the client of loaded nodes if they are logged in
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="loadedNodes">Can be empty.  In which case, nothing happens</param>
 | 
			
		||||
        private void UpdateClientWithLoadedNodes(UserAccount userInfo, List<InventoryNodeBase> loadedNodes)
 | 
			
		||||
        private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes)
 | 
			
		||||
        {
 | 
			
		||||
            if (loadedNodes.Count == 0)
 | 
			
		||||
                return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -514,7 +514,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 | 
			
		|||
            UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
 | 
			
		||||
            
 | 
			
		||||
            Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
 | 
			
		||||
            List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>();
 | 
			
		||||
            HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>();
 | 
			
		||||
            
 | 
			
		||||
            string folder1Name = "1";
 | 
			
		||||
            string folder2aName = "2a";
 | 
			
		||||
| 
						 | 
				
			
			@ -529,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 | 
			
		|||
 | 
			
		||||
            {
 | 
			
		||||
                // Test replication of path1
 | 
			
		||||
                new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null)
 | 
			
		||||
                new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
 | 
			
		||||
                    .ReplicateArchivePathToUserInventory(
 | 
			
		||||
                        iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
 | 
			
		||||
                        foldersCreated, nodesLoaded);
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 | 
			
		|||
            
 | 
			
		||||
            {
 | 
			
		||||
                // Test replication of path2
 | 
			
		||||
                new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null)
 | 
			
		||||
                new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
 | 
			
		||||
                    .ReplicateArchivePathToUserInventory(
 | 
			
		||||
                        iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
 | 
			
		||||
                        foldersCreated, nodesLoaded);
 | 
			
		||||
| 
						 | 
				
			
			@ -592,10 +592,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 | 
			
		|||
            
 | 
			
		||||
            string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
 | 
			
		||||
            
 | 
			
		||||
            new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null)
 | 
			
		||||
            new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
 | 
			
		||||
                .ReplicateArchivePathToUserInventory(
 | 
			
		||||
                    itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
 | 
			
		||||
                    new Dictionary<string, InventoryFolderBase>(), new List<InventoryNodeBase>());
 | 
			
		||||
                    new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
 | 
			
		||||
 | 
			
		||||
            List<InventoryFolderBase> folder1PostCandidates 
 | 
			
		||||
                = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
 | 
			
		||||
| 
						 | 
				
			
			@ -617,5 +617,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 | 
			
		|||
                = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b");
 | 
			
		||||
            Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
 | 
			
		||||
        }       
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Test replication of a partly existing archive path to the user's inventory.  This should create
 | 
			
		||||
        /// a merged path.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [Test]
 | 
			
		||||
        public void TestMergeIarPath()
 | 
			
		||||
        {
 | 
			
		||||
            TestHelper.InMethod();
 | 
			
		||||
            log4net.Config.XmlConfigurator.Configure();
 | 
			
		||||
            
 | 
			
		||||
            Scene scene = SceneSetupHelpers.SetupScene("inventory");
 | 
			
		||||
            UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
 | 
			
		||||
            
 | 
			
		||||
            string folder1ExistingName = "a";
 | 
			
		||||
            string folder2Name = "b";
 | 
			
		||||
            
 | 
			
		||||
            InventoryFolderBase folder1 
 | 
			
		||||
                = UserInventoryTestUtils.CreateInventoryFolder(
 | 
			
		||||
                    scene.InventoryService, ua1.PrincipalID, folder1ExistingName);            
 | 
			
		||||
            
 | 
			
		||||
            string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
 | 
			
		||||
            string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
 | 
			
		||||
            
 | 
			
		||||
            string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
 | 
			
		||||
            
 | 
			
		||||
            new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true)
 | 
			
		||||
                .ReplicateArchivePathToUserInventory(
 | 
			
		||||
                    itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
 | 
			
		||||
                    new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
 | 
			
		||||
 | 
			
		||||
            List<InventoryFolderBase> folder1PostCandidates 
 | 
			
		||||
                = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
 | 
			
		||||
            Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
 | 
			
		||||
            Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
 | 
			
		||||
 | 
			
		||||
            List<InventoryFolderBase> folder2PostCandidates 
 | 
			
		||||
                = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b");
 | 
			
		||||
            Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
 | 
			
		||||
        }           
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
/*
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
 * See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -173,16 +173,16 @@ namespace OpenSim.Region.CoreModules.Framework.Library
 | 
			
		|||
                m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
 | 
			
		||||
                simpleName = GetInventoryPathFromName(simpleName);
 | 
			
		||||
 | 
			
		||||
                InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName);
 | 
			
		||||
                InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false);
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    List<InventoryNodeBase> nodes = archread.Execute();
 | 
			
		||||
                    HashSet<InventoryNodeBase> nodes = archread.Execute();
 | 
			
		||||
                    if (nodes != null && nodes.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        // didn't find the subfolder with the given name; place it on the top
 | 
			
		||||
                        m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
 | 
			
		||||
                        archread.Close();
 | 
			
		||||
                        archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName);
 | 
			
		||||
                        archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false);
 | 
			
		||||
                        archread.Execute();
 | 
			
		||||
                    }
 | 
			
		||||
                    foreach (InventoryNodeBase node in nodes)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
/*
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
 * See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue