Description
I propose adding the following function:
package os
// InRoot returns a Root that operates on the named directory.
//
// The directory is opened anew at the start of every operation on the Root.
// If the directory cannot be opened, the operation returns an error.
// The directory is closed after every operation. Calling Close on the Root does nothing.
//
// InRoot may be used for one-off operations rooted in a directory.
// For example:
//
// // Remove name in dir.
// err := os.InRoot(dir).Remove(name)
func InRoot(name string) *Root
os.Root
(#67002) supports performing filesystem operations within the context of some directory.
Performing a single operation in a Root is substantially more verbose than doing so outside of one. Compare:
f, err := os.Create(filepath.Join(base, name))
root, err := os.OpenRoot(base)
if err != nil {
return err
}
defer root.Close()
f, err := root.Create(name)
If the Root
will be reused for many operations, the additional overhead of opening and closing it is not so significant. For a single operation, however, it's enough to be annoying.
We have an os.OpenInRoot
convenience function for opening files, but this covers only one operation. We could add similar functions for other operations (os.CreateInRoot
, os.RemoveInRoot
, etc.), but that would be a lot of new functions.
This has come up in the context of #73126, which proposes adding Root.ReadFile
and Root.WriteFile
methods: #73126 (comment) asks if we can have top-level convenience functions as well, since opening and closing the root for short operations is inconvenient.
I've also had this raised in a Google-internal discussion: We have a linter which recommends using the github.com/google/safeopen
package for certain operations (recommending, for example, that os.Create(filepath.Join(a, b))
could be safeopen.CreateBeneath(a, b)
). We're reluctant to change the linter to recommend os.Root
in cases where a one-liner becomes several lines opening and closing a Root.
The InRoot
function allows performing operations in a root with slightly less verbosity than the non-rooted equivalent using filepath.Join
. To continue the above example:
f, err := os.InRoot(base).Create(name)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status