// Both rootPath/childPath are like "/" and "/users"
// Assumption is that both are well-formed paths.
// Returns a path without a trailing "/" unless the overall path is just "/"
190768
func appendPath(rootPath, childPath string) string {
	return strings.TrimRight(rootPath, "/") + "/" + strings.TrimLeft(childPath, "/")
}
1113381
func Path(s string) string {
	// Start with lowercase string
	filePath := strings.ToLower(s)
	filePath = strings.Replace(filePath, "..", "", -1)
	filePath = path.Clean(filePath)

	// Remove illegal characters for paths, flattening accents
	// and replacing some common separators with -
	filePath = cleanString(filePath, illegalPath)

	// NB this may be of length 0, caller must check
	return filePath
}
637267
func ParsePath(str string) (path Path, ok bool) {
	if len(str) == 0 {
		return nil, false
	}
	if str[0] != '/' {
		return nil, false
	}
	if len(str) == 1 {
		return Path{}, true
	}
	parts := strings.Split(str[1:], "/")
	return parts, true
}
1146439
func SplitPathDirEntry(path string) (dir, base string) {
	cleanedPath := filepath.Clean(filepath.FromSlash(path))

	if specifiesCurrentDir(path) {
		cleanedPath += string(os.PathSeparator) + "."
	}

	return filepath.Dir(cleanedPath), filepath.Base(cleanedPath)
}
745658
func (s GeoDistanceSort) NestedPath(nestedPath string) GeoDistanceSort {
	s.nestedPath = &nestedPath
	return s
}
317521
func rootPath(root, path string, cb onSymlinkFunc) (string, error) {
	if path == "" {
		return root, nil
	}
	var linksWalked int // to protect against cycles
	for {
		i := linksWalked
		newpath, err := walkLinks(root, path, &linksWalked, cb)
		if err != nil {
			return "", err
		}
		path = newpath
		if i == linksWalked {
			newpath = filepath.Join("/", newpath)
			if path == newpath {
				return filepath.Join(root, newpath), nil
			}
			path = newpath
		}
	}
}
1166178
func IsSubpath(path, root string) bool {
	path, err := filepath.Abs(filepath.Clean(path))
	if err != nil {
		return false
	}
	root, err = filepath.Abs(filepath.Clean(root))
	if err != nil {
		return false
	}
	if root == path {
		return true
	}
	if root[len(root)-1] != filepath.Separator {
		root += string(filepath.Separator)
	}
	return strings.HasPrefix(path, root)
}
653085
func (p Path) Join(childName string) (childPath Path, err error) {
	switch p.PathType {
	case RootPathType:
		if childName != topName {
			err = CannotJoinPathErr{p, childName}
			return
		}

		childPath = Path{
			PathType: KeybasePathType,
		}
		return

	case KeybasePathType:
		if childName != publicName && childName != privateName {
			err = CannotJoinPathErr{p, childName}
		}

		childPath = Path{
			PathType: KeybaseChildPathType,
			TLFType:  listTypeToTLFType(childName),
		}
		return

	case KeybaseChildPathType:
		childPath = Path{
			PathType: TLFPathType,
			TLFType:  p.TLFType,
			TLFName:  childName,
		}
		return

	case TLFPathType:
		childPath = Path{
			PathType:      TLFPathType,
			TLFType:       p.TLFType,
			TLFName:       p.TLFName,
			TLFComponents: append(p.TLFComponents, childName),
		}
		return
	}

	err = CannotJoinPathErr{p, childName}
	return
}
265287
func subdirs(path string) (paths []string) {
	filepath.Walk(path, func(subpath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			name := info.Name()
			hidden := filepath.HasPrefix(name, ".") && name != "." && name != ".."
			if hidden {
				return filepath.SkipDir
			}
			paths = append(paths, subpath)
		}
		return nil
	})
	return paths
}
839798
func (p Path) ChildPath(name string, ptr BlockPointer) Path {
	child := Path{
		FolderBranch: p.FolderBranch,
		Path:         make([]PathNode, len(p.Path), len(p.Path)+1),
	}
	copy(child.Path, p.Path)
	child.Path = append(child.Path, PathNode{Name: name, BlockPointer: ptr})
	return child
}
1124605
func (p Path) ChildPathNoPtr(name string) Path {
	return p.ChildPath(name, BlockPointer{})
}
87736
func (perm *Permissions) AddUserPath(prefix string) {
	perm.userPathPrefixes = append(perm.userPathPrefixes, prefix)
}
535931
func IsSubpath(basepath, maybeSubpath string) bool {
	rel, err := filepath.Rel(basepath, maybeSubpath)
	if err != nil {
		return false
	}
	if strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
		// not a subpath if "../" has to be used for the relative path
		return false
	}
	return true
}
278911
func isParentPath(parent, path string) bool {
	rel, err := filepath.Rel(parent, path)
	return err == nil && !strings.HasPrefix(rel, "..")
}
246030
func (fp *FieldPath) Root() *FieldPath {
	for ; fp.parent != nil; fp = fp.parent {
		// Do nothing.
	}
	return fp
}
1131078
func Path(baseDir string, name string) string {
	key := repoKeyStr(name)
	return filepath.Join(baseDir, key)
}
420771
func IsRelativePath(pth string) bool {
	if strings.HasPrefix(pth, "./") {
		return true
	}

	if strings.HasPrefix(pth, "/") {
		return false
	}

	if strings.HasPrefix(pth, "$") {
		return false
	}

	return true
}