/// <summary>
        /// Canonicalization normalizes an absolute path that may contain directory traversals like '.' or '..'
        /// to a path that cannot contain relative traversals and will always be a specific downward path from
        /// the root of the tree.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static CanonicalTreePath Canonicalize(AbsoluteTreePath path)
        {
            // Canonicalize the absolute path:
            List <string> parts = new List <string>(path.Parts.Count);

            foreach (string part in path.Parts)
            {
                // Just ignore '.' paths:
                if (part == ".")
                {
                    continue;
                }

                // Take a '..' and remove the last part of the path:
                if (part == "..")
                {
                    if (parts.Count == 0)
                    {
                        throw new InvalidPathError("traversed beyond the tree root with too many '..' path elements");
                    }

                    // Remove the last part of the absolute path built so far:
                    parts.RemoveAt(parts.Count - 1);
                    continue;
                }

                parts.Add(part);
            }

            return(new CanonicalTreePath(parts));
        }
 /// <summary>
 /// Creates an absolute blob path from an absolute tree path and a blob name.
 /// </summary>
 /// <param name="tree"></param>
 /// <param name="name"></param>
 public AbsoluteBlobPath(AbsoluteTreePath tree, string name)
 {
     this.Tree = tree;
     this.Name = name;
 }
 /// <summary>
 /// Creates an absolute blob path from an absolute tree path and a blob name.
 /// </summary>
 /// <param name="tree"></param>
 /// <param name="name"></param>
 public AbsoluteBlobPath(AbsoluteTreePath tree, string name)
 {
     this.Tree = tree;
     this.Name = name;
 }