github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/internal/pkg/pathtranslator/pathtranslator.go (about) 1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package pathtranslator provides path translation functions. 16 package pathtranslator 17 18 import ( 19 "os" 20 "path/filepath" 21 "strings" 22 ) 23 24 type mapperType func(string, string, string) string 25 26 // ListRelToExecRoot converts a list of paths that are either relative to workingDir or 27 // absolute, to paths relative to execRoot. workingDir is relative to execRoot. 28 // A path will be ignored if path is not relative to execRoot. 29 // Output path is operating system defined file path. 30 func ListRelToExecRoot(execRoot, workingDir string, paths []string) []string { 31 return mapPaths(execRoot, workingDir, paths, RelToExecRoot) 32 } 33 34 // ListRelToWorkingDir converts a list of paths that are either relative to the execroot or 35 // absolute, to paths relative to the workingDir. 36 // Output path is operating system defined file path. 37 func ListRelToWorkingDir(execRoot, workingDir string, paths []string) []string { 38 return mapPaths(execRoot, workingDir, paths, RelToWorkingDir) 39 } 40 41 // RelToExecRoot converts a path that is either relative to workingDir or absolute, to a 42 // path relative to execRoot. workingDir is relative to execRoot. 43 // It returns empty string if path is not relative to execRoot. 44 // Output path is operating system defined file path. 45 func RelToExecRoot(execRoot, workingDir, p string) string { 46 if p == "" { 47 return "" 48 } 49 if !filepath.IsAbs(p) { 50 p = filepath.Join(execRoot, workingDir, p) 51 } 52 rp, err := filepath.Rel(execRoot, p) 53 if err != nil { 54 return "" 55 } 56 if strings.HasPrefix(rp, "..") { 57 return "" 58 } 59 return rp 60 } 61 62 // RelToWorkingDir converts a path that is either relative to the execroot or absolute, 63 // to a path relative to the workingDir. 64 func RelToWorkingDir(execRoot, workingDir, p string) string { 65 if !filepath.IsAbs(p) { 66 p = filepath.Join(execRoot, p) 67 } 68 rp, err := filepath.Rel(filepath.Join(execRoot, workingDir), p) 69 if err != nil { 70 return "" 71 } 72 return rp 73 } 74 75 func mapPaths(execRoot, workingDir string, paths []string, mapper mapperType) []string { 76 var res []string 77 for _, p := range paths { 78 if rel := mapper(execRoot, workingDir, p); rel != "" { 79 res = append(res, rel) 80 } 81 } 82 return res 83 } 84 85 // BinaryRelToAbs converts a path that is relative to the current executable 86 // to an absolute path. If the executable is a symlink then the symlink is 87 // resolved before generating the path. 88 func BinaryRelToAbs(relPath string) (string, error) { 89 executable, err := os.Executable() 90 if err != nil { 91 return "", err 92 } 93 executable, err = filepath.EvalSymlinks(executable) 94 if err != nil { 95 return "", err 96 } 97 uploader := filepath.Join(filepath.Dir(executable), relPath) 98 return uploader, nil 99 }