github.com/richardwilkes/toolbox@v1.121.0/xio/fs/roots.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package fs 11 12 import ( 13 "path/filepath" 14 "strings" 15 16 "github.com/richardwilkes/toolbox/errs" 17 ) 18 19 // UniquePaths returns a list of unique paths from the given paths, pruning out paths that are a subset of another. 20 func UniquePaths(paths ...string) ([]string, error) { 21 set := make(map[string]bool, len(paths)) 22 for _, path := range paths { 23 actual, err := filepath.Abs(path) 24 if err != nil { 25 return nil, errs.NewWithCause(path, err) 26 } 27 if actual, err = filepath.EvalSymlinks(actual); err != nil { 28 return nil, errs.NewWithCause(path, err) 29 } 30 if _, exists := set[actual]; !exists { 31 add := true 32 for one := range set { 33 var p1, p2 string 34 if p1, err = filepath.Rel(one, actual); err != nil { 35 return nil, errs.NewWithCause(path, err) 36 } 37 if p2, err = filepath.Rel(actual, one); err != nil { 38 return nil, errs.NewWithCause(path, err) 39 } 40 prefixed := strings.HasPrefix(p1, "..") 41 if prefixed != strings.HasPrefix(p2, "..") { 42 if prefixed { 43 delete(set, one) 44 } else { 45 add = false 46 break 47 } 48 } 49 } 50 if add { 51 set[actual] = true 52 } 53 } 54 } 55 result := make([]string, 0, len(set)) 56 for p := range set { 57 result = append(result, p) 58 } 59 return result, nil 60 }