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  }