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 }