github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/workdir/normalize_path.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package workdir
     5  
     6  import (
     7  	"path/filepath"
     8  )
     9  
    10  // NormalizePath attempts to transform the given path so that it's relative
    11  // to the working directory, which is our preferred way to present and store
    12  // paths to files and directories within a configuration so that they can
    13  // be portable to operations in other working directories.
    14  //
    15  // It isn't always possible to produce a relative path. For example, on Windows
    16  // the given path might be on a different volume (e.g. drive letter or network
    17  // share) than the working directory.
    18  //
    19  // Note that the result will be relative to the main directory of the receiver,
    20  // which should always be the actual process working directory in normal code,
    21  // but might be some other temporary working directory when in test code.
    22  // If you need to access the file or directory that the result refers to with
    23  // functions that aren't aware of our base directory, you can use something
    24  // like the following, which again should be needed only in test code which
    25  // might need to inspect the filesystem in order to make assertions:
    26  //
    27  //	filepath.Join(d.RootModuleDir(), normalizePathResult)
    28  //
    29  // The above is suitable only for situations where the given path is known
    30  // to be beneath the working directory, which is the typical situation for
    31  // temporary working directories created for automated tests.
    32  func (d *Dir) NormalizePath(given string) string {
    33  	// We need an absolute version of d.mainDir in order for our "Rel"
    34  	// result to be reliable.
    35  	absMain, err := filepath.Abs(d.mainDir)
    36  	if err != nil {
    37  		// Weird, but okay...
    38  		return filepath.Clean(given)
    39  	}
    40  
    41  	if !filepath.IsAbs(given) {
    42  		given = filepath.Join(absMain, given)
    43  	}
    44  
    45  	ret, err := filepath.Rel(absMain, given)
    46  	if err != nil {
    47  		// It's not always possible to find a relative path. For example,
    48  		// the given path might be on an entirely separate volume
    49  		// (e.g. drive letter or network share) on a Windows system, which
    50  		// always requires an absolute path.
    51  		return filepath.Clean(given)
    52  	}
    53  
    54  	return ret
    55  }