From 72bd68a21f916db918aeb3dd60a1f391e41ed7c2 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Fri, 4 Jun 2010 22:17:23 +0100
Subject: add ability for load iar/save iar to take in arbitrary options

not used for anything yet
---
 .../Inventory/Archiver/InventoryArchiverModule.cs  | 67 +++++++++++++++-------
 .../Interfaces/IInventoryArchiverModule.cs         | 29 ++++++++++
 2 files changed, 76 insertions(+), 20 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index ab5f485..cfefbe9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -30,11 +30,11 @@ using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
 using log4net;
+using NDesk.Options;
 using Nini.Config;
 using OpenMetaverse;
 using OpenSim.Framework;
 using OpenSim.Framework.Communications;
-
 using OpenSim.Region.Framework.Interfaces;
 using OpenSim.Region.Framework.Scenes;
 using OpenSim.Services.Interfaces;
@@ -91,9 +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).",
-                    "<first> is user's first name." + Environment.NewLine
+				    //"--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				                 
                     + "<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
@@ -133,8 +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)
+		
+        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>());
+		}
+
+        public bool ArchiveInventory(
+		    Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 
+		    Dictionary<string, object> options)
         {
             if (m_scenes.Count > 0)
             {
@@ -172,7 +183,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             return false;
         }
                         
-        public bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, string savePath)
+        public bool ArchiveInventory(
+		    Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 
+		    Dictionary<string, object> options)
         {
             if (m_scenes.Count > 0)
             {
@@ -209,8 +222,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             
             return false;
         }
-              
+
         public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream)
+		{
+			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)
         {
             if (m_scenes.Count > 0)
             {
@@ -252,7 +272,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             return false;
         }
         
-        public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, string loadPath)
+        public bool DearchiveInventory(
+		     string firstName, string lastName, string invPath, string pass, string loadPath, 
+		     Dictionary<string, object> options)
         {
             if (m_scenes.Count > 0)
             {
@@ -300,29 +322,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// <param name="cmdparams"></param>
         protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams)
         {
-            if (cmdparams.Length < 6)
+			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(
                     "[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]");
                 return;
-            }
+            }            
 
-            m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL.  BUG REPORTS WELCOME.");
-
-            string firstName = cmdparams[2];
-            string lastName = cmdparams[3];
-            string invPath = cmdparams[4];
-            string pass = cmdparams[5];
-            string loadPath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME);
+            string firstName = mainParams[2];
+            string lastName = mainParams[3];
+            string invPath = mainParams[4];
+            string pass = mainParams[5];
+            string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
 
             m_log.InfoFormat(
                 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
                 loadPath, invPath, firstName, lastName);
             
-            if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath))
+            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>
@@ -351,7 +378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 savePath, invPath, firstName, lastName);
 
             Guid id = Guid.NewGuid();
-            ArchiveInventory(id, firstName, lastName, invPath, pass, savePath);
+            ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary<string, object>());
 
             lock (m_pendingConsoleSaves)
                 m_pendingConsoleSaves.Add(id);
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
index fbadd91..01066e6 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
@@ -26,6 +26,7 @@
  */
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 using OpenSim.Services.Interfaces;
 
@@ -59,6 +60,20 @@ namespace OpenSim.Region.Framework.Interfaces
         /// <param name="loadStream">The stream from which the inventory archive will be loaded</param>
         /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
         bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream);
+		
+        /// <summary>
+        /// Dearchive a user's inventory folder from the given stream
+        /// </summary>
+        /// <param name="firstName"></param>
+        /// <param name="lastName"></param>
+        /// <param name="invPath">The inventory path in which to place the loaded folders and items</param>
+        /// <param name="loadStream">The stream from which the inventory archive will be loaded</param>
+        /// <param name="options">Dearchiving options.  At the moment, the only option is ("merge", true).  This merges
+        /// the loaded IAR with existing folders where possible.</param>
+        /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
+        bool DearchiveInventory(
+			string firstName, string lastName, string invPath, string pass, Stream loadStream, 
+		    Dictionary<string, object> options);		
 
         /// <summary>
         /// Archive a user's inventory folder to the given stream
@@ -70,5 +85,19 @@ namespace OpenSim.Region.Framework.Interfaces
         /// <param name="saveStream">The stream to which the inventory archive will be saved</param>
         /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
         bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream);
+		
+        /// <summary>
+        /// Archive a user's inventory folder to the given stream
+        /// </summary>
+        /// <param name="id">ID representing this request.  This will later be returned in the save event</param>
+        /// <param name="firstName"></param>
+        /// <param name="lastName"></param>
+        /// <param name="invPath">The inventory path from which the inventory should be saved.</param>
+        /// <param name="saveStream">The stream to which the inventory archive will be saved</param>
+        /// <param name="options">Archiving options.  Currently, there are none.</param>
+        /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
+        bool ArchiveInventory(
+		    Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 
+		    Dictionary<string, object> options);		
     }
 }
-- 
cgit v1.1


From 3c3df9f3e9fbf9955c0939116e9bfeed1d429fa6 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Fri, 4 Jun 2010 23:34:42 +0100
Subject: refactor: do pathname trimming outside of
 ReplicateArchivePathToUserInventory()

---
 .../Inventory/Archiver/InventoryArchiveReadRequest.cs   | 17 +++++++----------
 .../Inventory/Archiver/Tests/InventoryArchiverTests.cs  |  2 +-
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 806aa4f..256a886 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -139,10 +139,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                     }
                     else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                     {
+                        filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);
+                        
+                        // Trim off the file portion if we aren't already dealing with a directory path
+                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
+                            filePath = filePath.Remove(filePath.LastIndexOf("/") + 1);
+                        
                         InventoryFolderBase foundFolder 
                             = ReplicateArchivePathToUserInventory(
-                                filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, 
-                                rootDestinationFolder, foldersCreated, nodesLoaded);
+                                filePath, rootDestinationFolder, foldersCreated, nodesLoaded);
     
                         if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                         {
@@ -184,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// Replicate the inventory paths in the archive to the user's inventory as necessary.
         /// </summary>
         /// <param name="archivePath">The item archive path to replicate</param>
-        /// <param name="isDir">Is the path we're dealing with a directory?</param>
         /// <param name="rootDestinationFolder">The root folder for the inventory load</param>
         /// <param name="foldersCreated">
         /// The folders created so far.  This method will add more folders if necessary
@@ -196,17 +200,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// <returns>The last user inventory folder created or found for the archive path</returns>
         public InventoryFolderBase ReplicateArchivePathToUserInventory(
             string archivePath, 
-            bool isDir, 
             InventoryFolderBase rootDestFolder, 
             Dictionary <string, InventoryFolderBase> foldersCreated,
             List<InventoryNodeBase> nodesLoaded)
         {
-            archivePath = archivePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);
-
-            // Remove the file portion if we aren't already dealing with a directory path
-            if (!isDir)
-                archivePath = archivePath.Remove(archivePath.LastIndexOf("/") + 1);
-
             string originalArchivePath = archivePath;
 
 //            m_log.DebugFormat(
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 507662f..cb6bf76 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -531,7 +531,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
 
             new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null)
                 .ReplicateArchivePathToUserInventory(
-                    itemArchivePath, false, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
+                    itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 
                     foldersCreated, nodesLoaded);
 
             InventoryFolderBase folder1 
-- 
cgit v1.1


From 63797445be561730e7d117573813ca12c02bc6f1 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Sat, 5 Jun 2010 00:48:33 +0100
Subject: various refactorings on methods to replicate IAR paths to user
 inventory in order to improve readability

---
 .../Archiver/InventoryArchiveReadRequest.cs        | 208 +++++++++++++--------
 .../Archiver/Tests/InventoryArchiverTests.cs       |   2 +-
 2 files changed, 128 insertions(+), 82 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 256a886..60d1720 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -97,9 +97,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             int successfulAssetRestores = 0;
             int failedAssetRestores = 0;
             int successfulItemRestores = 0;
-            List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>();
+            
+            List<InventoryNodeBase> loadedNodes = new List<InventoryNodeBase>();
            
-            //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
             InventoryFolderBase rootDestinationFolder 
                 = InventoryArchiveUtils.FindFolderByPath(
                     m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath);
@@ -109,14 +109,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 // Possibly provide an option later on to automatically create this folder if it does not exist
                 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
 
-                return nodesLoaded;
+                return loadedNodes;
             }
 
             archive = new TarArchiveReader(m_loadStream);
 
             // In order to load identically named folders, we need to keep track of the folders that we have already
-            // created
-            Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
+            // resolved
+            Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>();
 
             byte[] data;
             TarArchiveReader.TarEntryType entryType;
@@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                         
                         InventoryFolderBase foundFolder 
                             = ReplicateArchivePathToUserInventory(
-                                filePath, rootDestinationFolder, foldersCreated, nodesLoaded);
+                                filePath, rootDestinationFolder, resolvedFolders, loadedNodes);
     
                         if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                         {
@@ -160,7 +160,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                                 // 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)
-                                    nodesLoaded.Add(item);
+                                    loadedNodes.Add(item);
                             }
                         }
                     }
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 successfulAssetRestores, failedAssetRestores);
             m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);
 
-            return nodesLoaded;
+            return loadedNodes;
         }
 
         public void Close()
@@ -190,45 +190,118 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// </summary>
         /// <param name="archivePath">The item archive path to replicate</param>
         /// <param name="rootDestinationFolder">The root folder for the inventory load</param>
-        /// <param name="foldersCreated">
-        /// The folders created so far.  This method will add more folders if necessary
+        /// <param name="resolvedFolders">
+        /// The folders that we have resolved so far for a given archive path.  
+        /// This method will add more folders if necessary
         /// </param>
-        /// <param name="nodesLoaded">
-        /// Track the inventory nodes created.  This is distinct from the folders created since for a particular folder
-        /// chain, only the root node needs to be recorded
+        /// <param name="loadedNodes">
+        /// Track the inventory nodes created.
         /// </param>
         /// <returns>The last user inventory folder created or found for the archive path</returns>
         public InventoryFolderBase ReplicateArchivePathToUserInventory(
             string archivePath, 
             InventoryFolderBase rootDestFolder, 
-            Dictionary <string, InventoryFolderBase> foldersCreated,
-            List<InventoryNodeBase> nodesLoaded)
+            Dictionary <string, InventoryFolderBase> resolvedFolders,
+            List<InventoryNodeBase> loadedNodes)
         {
             string originalArchivePath = archivePath;
 
 //            m_log.DebugFormat(
 //                "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
+                        
+            InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref archivePath, resolvedFolders);
+            
+//            m_log.DebugFormat(
+//                "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", 
+//                originalArchivePath, archivePath);
+            
+            string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length);
+            CreateFoldersForPath(destFolder, archivePathSectionToCreate, resolvedFolders, loadedNodes);
+            
+            return destFolder;
+            
+            /*
+            string[] rawFolders = filePath.Split(new char[] { '/' });
+
+            // Find the folders that do exist along the path given
+            int i = 0;
+            bool noFolder = false;
+            InventoryFolderImpl foundFolder = rootDestinationFolder;
+            while (!noFolder && i < rawFolders.Length)
+            {
+                InventoryFolderImpl folder = foundFolder.FindFolderByPath(rawFolders[i]);
+                if (null != folder)
+                {
+                    m_log.DebugFormat("[INVENTORY ARCHIVER]: Found folder {0}", folder.Name);
+                    foundFolder = folder;
+                    i++;
+                }
+                else
+                {
+                    noFolder = true;
+                }
+            }
+
+            // Create any folders that did not previously exist
+            while (i < rawFolders.Length)
+            {
+                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawFolders[i]);
+
+                UUID newFolderId = UUID.Random();
+                m_userInfo.CreateFolder(
+                    rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
+                foundFolder = foundFolder.GetChildFolder(newFolderId);
+            }
+            */
+        }
+
+        /// <summary>
+        /// Resolve a destination folder
+        /// </summary>
+        /// 
+        /// We require here a root destination folder (usually the root of the user's inventory) and the archive
+        /// path.  We also pass in a list of previously resolved folders in case we've found this one previously.
+        /// 
+        /// <param name="archivePath">
+        /// The item archive path to resolve.  The portion of the path passed back is that
+        /// which corresponds to the resolved desintation folder.
+        /// <param name="rootDestinationFolder">
+        /// The root folder for the inventory load
+        /// </param>
+        /// <param name="resolvedFolders">
+        /// The folders that we have resolved so far for a given archive path.  
+        /// </param>
+        /// <returns>
+        /// The folder in the user's inventory that matches best the archive path given.  If no such folder was found
+        /// then the passed in root destination folder is returned.
+        /// </returns>        
+        protected InventoryFolderBase ResolveDestinationFolder(
+            InventoryFolderBase rootDestFolder,                                                             
+            ref string archivePath,             
+            Dictionary <string, InventoryFolderBase> resolvedFolders)
+        {
+            string originalArchivePath = archivePath;
 
             InventoryFolderBase destFolder = null;
 
-            // XXX: Nasty way of dealing with a path that has no directory component
             if (archivePath.Length > 0)
             {
                 while (null == destFolder && archivePath.Length > 0)
                 {
-                    if (foldersCreated.ContainsKey(archivePath))
+                    if (resolvedFolders.ContainsKey(archivePath))
                     {
 //                        m_log.DebugFormat(
 //                            "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
-                        destFolder = foldersCreated[archivePath];
+                        destFolder = resolvedFolders[archivePath];
                     }
                     else
                     {
-                        // Don't include the last slash
+                        // 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
@@ -242,19 +315,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                     }
                 }
             }
-            else
-            {
+            
+            if (null == destFolder)
                 destFolder = rootDestFolder;
-            }
-
-            string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length);
-            string[] rawDirsToCreate
-                = archivePathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+            
+            return destFolder;
+        }
+        
+        /// <summary>
+        /// Create a set of folders for the given path.
+        /// </summary>
+        /// <param name="destFolder">
+        /// The root folder from which the creation will take place.
+        /// </param>
+        /// <param name="path">
+        /// The path to create
+        /// </param>
+        /// <param name="resolvedFolders">
+        /// The folders that we have resolved so far for a given archive path.
+        /// </param>
+        /// <param name="loadedNodes">
+        /// Track the inventory nodes created.
+        /// </param>
+        protected void CreateFoldersForPath(
+            InventoryFolderBase destFolder, string path, Dictionary <string, InventoryFolderBase> resolvedFolders, 
+            List<InventoryNodeBase> loadedNodes)
+        {
+            string pathCreated = "";
+            string[] rawDirsToCreate = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
             int i = 0;
 
             while (i < rawDirsToCreate.Length)
             {
-                m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading archived folder {0}", rawDirsToCreate[i]);
+//                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
 
                 int identicalNameIdentifierIndex
                     = rawDirsToCreate[i].LastIndexOf(
@@ -279,66 +372,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                         newFolderId, newFolderName, m_userInfo.PrincipalID, 
                         (short)AssetType.Unknown, destFolder.ID, 1);
                 m_scene.InventoryService.AddFolder(destFolder);
-                
-//                UUID newFolderId = UUID.Random();
-//                m_scene.InventoryService.AddFolder(
-//                m_userInfo.CreateFolder(
-//                    folderName, newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
-
-//                m_log.DebugFormat("[INVENTORY ARCHIVER]: Retrieving newly created folder {0}", folderName);
-//                foundFolder = foundFolder.GetChildFolder(newFolderId);
-//                m_log.DebugFormat(
-//                    "[INVENTORY ARCHIVER]: Retrieved newly created folder {0} with ID {1}", 
-//                    foundFolder.Name, foundFolder.ID);
 
                 // Record that we have now created this folder
-                archivePath += rawDirsToCreate[i] + "/";
-                m_log.DebugFormat("[INVENTORY ARCHIVER]: Loaded archive path {0}", archivePath);
-                foldersCreated[archivePath] = destFolder;
+                pathCreated += rawDirsToCreate[i] + "/";
+                m_log.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", pathCreated);
+                resolvedFolders[pathCreated] = destFolder;
 
                 if (0 == i)
-                    nodesLoaded.Add(destFolder);
+                    loadedNodes.Add(destFolder);
 
                 i++;
-            }
-            
-            return destFolder;
-            
-            /*
-            string[] rawFolders = filePath.Split(new char[] { '/' });
-
-            // Find the folders that do exist along the path given
-            int i = 0;
-            bool noFolder = false;
-            InventoryFolderImpl foundFolder = rootDestinationFolder;
-            while (!noFolder && i < rawFolders.Length)
-            {
-                InventoryFolderImpl folder = foundFolder.FindFolderByPath(rawFolders[i]);
-                if (null != folder)
-                {
-                    m_log.DebugFormat("[INVENTORY ARCHIVER]: Found folder {0}", folder.Name);
-                    foundFolder = folder;
-                    i++;
-                }
-                else
-                {
-                    noFolder = true;
-                }
-            }
-
-            // Create any folders that did not previously exist
-            while (i < rawFolders.Length)
-            {
-                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawFolders[i]);
-
-                UUID newFolderId = UUID.Random();
-                m_userInfo.CreateFolder(
-                    rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
-                foundFolder = foundFolder.GetChildFolder(newFolderId);
-            }
-            */
+            }            
         }
-
+        
         /// <summary>
         /// Load an item from the archive
         /// </summary>
@@ -429,4 +475,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index cb6bf76..59cd386 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -279,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
         public void TestIarV0_1WithEscapedChars()
         {
             TestHelper.InMethod();
-//            log4net.Config.XmlConfigurator.Configure();
+            log4net.Config.XmlConfigurator.Configure();
 
             string itemName = "You & you are a mean/man/";
             string humanEscapedItemName = @"You & you are a mean\/man\/";
-- 
cgit v1.1


From fe3e1c67aeb00097b2fcfb2c0c6828e9c49d7a9c Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Sat, 5 Jun 2010 06:56:36 -0700
Subject: Bug fix: update the list of friends upon MakeRoot, because child
 agents don't get notified of new friendships.

---
 OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 0050653..3590f27 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -267,7 +267,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
 
             if (m_Friends.ContainsKey(agentID))
             {
-                if (m_Friends[agentID].RegionID == UUID.Zero && m_Friends[agentID].Friends == null)
+                if (m_Friends[agentID].RegionID == UUID.Zero)
                 {
                     m_Friends[agentID].Friends =
                             m_FriendsService.GetFriends(agentID);
-- 
cgit v1.1


From ab3afd5f42593cb6f5475af36accdd1f01962fd1 Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Sat, 5 Jun 2010 09:39:09 -0700
Subject: * Bug fix in TP home: typo in unpacking of GridUserInfo. * Bug fix in
 TPs across neighboring regions: bug was introduced when getting rid of
 crashed sessions.

---
 .../Framework/EntityTransfer/EntityTransferModule.cs          | 11 +++++++++++
 OpenSim/Region/Framework/Scenes/Scene.cs                      |  2 ++
 .../Services/Connectors/GridUser/GridUserServiceConnector.cs  |  2 --
 OpenSim/Services/Interfaces/IGridUserService.cs               |  2 +-
 4 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ef37f63..1e3e0c9 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -410,6 +410,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
                                                                 teleportFlags, capsPath);
                 }
 
+                // Let's set this to true tentatively. This does not trigger OnChildAgent
+                sp.IsChildAgent = true;
+
                 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                 // that the client contacted the destination before we send the attachments and close things here.
@@ -418,6 +421,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
                     // Client never contacted destination. Let's restore everything back
                     sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
 
+                    // Fail. Reset it back
+                    sp.IsChildAgent = false;
+
                     ResetFromTransit(sp.UUID);
 
                     // Yikes! We should just have a ref to scene here.
@@ -436,7 +442,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
 
                 KillEntity(sp.Scene, sp.LocalId);
 
+                // Now let's make it officially a child agent
                 sp.MakeChildAgent();
+
                 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
 
                 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
@@ -538,6 +546,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
                     client.SendTeleportFailed("Your home region could not be found.");
                     return;
                 }
+                m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", 
+                    regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize);
+
                 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point...
                 ((Scene)(client.Scene)).RequestTeleportLocation(
                     client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 6300665..3948f14 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3990,7 +3990,9 @@ namespace OpenSim.Region.Framework.Scenes
                 // bordercross if position is outside of region
 
                 if (!result)
+                {
                     regionHandle = m_regInfo.RegionHandle;
+                }
                 else
                 {
                     // not in this region, undo the shift!
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
index 600ddfd..935ebb1 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
@@ -206,9 +206,7 @@ namespace OpenSim.Services.Connectors
                     if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
                     {
                         if (replyData["result"] is Dictionary<string, object>)
-                        {
                             guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]);
-                        }
                     }
 
                     return guinfo;
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index e629dff..95ce5e8 100644
--- a/OpenSim/Services/Interfaces/IGridUserService.cs
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces
                 Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt);
 
             if (kvp.ContainsKey("LastRegionID"))
-                UUID.TryParse(kvp["LastRegionID"].ToString(), out HomeRegionID);
+                UUID.TryParse(kvp["LastRegionID"].ToString(), out LastRegionID);
             if (kvp.ContainsKey("LastPosition"))
                 Vector3.TryParse(kvp["LastPosition"].ToString(), out LastPosition);
             if (kvp.ContainsKey("LastLookAt"))
-- 
cgit v1.1


From d91bd7646dc25e5e2ec20aaad596a168e0804436 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Mon, 7 Jun 2010 00:09:22 +0200
Subject: Add a call to SOG.ResumeScripts() after region crossing / teleport

---
 OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 3948f14..2544359 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2467,6 +2467,8 @@ namespace OpenSim.Region.Framework.Scenes
             
             newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1);
 
+            newObject.ResumeScripts();
+
             // Do this as late as possible so that listeners have full access to the incoming object
             EventManager.TriggerOnIncomingSceneObject(newObject);
             
-- 
cgit v1.1