public void CopyNFSFolder()
        {
            var root = NFSFolder.CreateRoot();

            var folder1 = new NFSFolder(1, "Folder 1");
            var folder2 = new NFSFolder(2, "Folder 2");

            root.Add(folder1);
            root.Add(folder2);

            var copyRoot = root.Copy();

            Assert.AreNotSame(folder1, copyRoot.Folders.First());
            Assert.AreNotSame(folder2, copyRoot.Folders.ElementAt(1));

            folder1.Add(folder2);

            Assert.AreSame(root.Folders.First().Folders.First(), folder2);
            Assert.IsFalse(copyRoot.Folders.First().Folders.Any());
        }
        private NFSFolder buildMethod(IProgressReporter reporter)
        {
            var report = reporter != null;

            var root       = NFSFolder.CreateRoot();
            var nfsFolders = this.GetRoot().Folders.ToList();

            var branchesManager = this.branchesManager;
            var branches        = branchesManager.Branches;
            var nodeRefCountMap = branchesManager.CreateRefMap();

            var total   = nodeRefCountMap.NodesCount;
            int current = 0;

            foreach (var branch in branches)
            {
                if (report)
                {
                    reporter.Report("build " + branch.FullPath);
                }

                var nodes      = branch.Nodes;
                int nodesCount = branch.NodeCount;

                var matchedStack = new Stack <NFSFolderNodePair>(nodesCount);
                foreach (var node in nodes)
                {
                    var folder = nfsFolders
                                 .FirstOrDefault(item => item.Name == node.Name);
                    if (folder == null)
                    {
                        break;
                    }

                    matchedStack.Push(new NFSFolderNodePair(folder, node));
                }

                if (matchedStack.Count != nodesCount)
                {
                    throw new Exception(string.Format("[{0}] not match to [{1}]",
                                                      string.Join(", ", matchedStack.Select(item => item.Folder.Name)),
                                                      branch.FullPath));
                }

                //add inner folder to outer parent folder
                NFSFolder subFolder = null;
                while (matchedStack.Count > 0)
                {
                    var pair = matchedStack.Pop();

                    var folder = pair.Folder;
                    var node   = pair.Node;

                    int refCount = nodeRefCountMap.DecreaseReferenceCount(node);

                    if (report)
                    {
                        reporter.Report((double)(current++) / total);
                    }

                    if (refCount == 0)
                    {
                        nfsFolders.Remove(folder);
                    }

                    if (subFolder != null)
                    {
                        folder.Add(subFolder);
                    }

                    if (matchedStack.Count == 0)
                    {
                        root.Add(folder);
                        break;
                    }

                    subFolder = folder;
                }
            }

            if (nfsFolders.Count != 0)
            {
                throw new Exception(
                          string.Format("Unassigned folders: {0}", string.Join(", ", nfsFolders.Select(item => item.Name))));
            }

            return(root);
        }