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 }