github.com/opentofu/opentofu@v1.7.1/internal/command/workdir/normalize_path.go (about)

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