Compare commits
11 Commits
b64c318a4a
...
v1.8.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dbc3a00fe
|
||
|
|
e9b7c5539a
|
||
|
|
236165bec8
|
||
|
|
4cb0403e08
|
||
|
|
0318a9759b
|
||
|
|
1a93d5d9f3
|
||
|
|
5dc944cf21
|
||
|
|
77a85a4f84
|
||
|
|
43d1ddfeb8
|
||
|
|
db20c70d86
|
||
|
|
c0c924b75a
|
2
TODO
2
TODO
@@ -4,6 +4,8 @@
|
||||
--- https://github.com/hlandau/passlib
|
||||
-- incoprporated separately; https://git.r00t2.io/r00t2/PWGen (import r00t2.io/pwgen)
|
||||
|
||||
- auger needs to be build-constrained to linux.
|
||||
|
||||
- unit tests
|
||||
|
||||
- constants/vars for errors
|
||||
|
||||
9
auger/consts.go
Normal file
9
auger/consts.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package auger
|
||||
|
||||
const (
|
||||
augLensTpl string = "/augeas/load/%v" // A fmt.Sprintf string (single placeholder only) for Lens module roots.
|
||||
augFsTree string = "/files"
|
||||
augFsTpl string = augFsTree + "%v//%v" // A fmt.Sprintf string (first placeholder fspath, second placeholder includeDirective) for files to search for the includeDirective.
|
||||
augInclTfm string = "incl" // The transformer keyword for Augeas includes.
|
||||
augAppendSuffix string = "[last()+1]"
|
||||
)
|
||||
97
auger/funcs.go
Normal file
97
auger/funcs.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package auger
|
||||
|
||||
import (
|
||||
`io/fs`
|
||||
`os`
|
||||
`strings`
|
||||
|
||||
`honnef.co/go/augeas`
|
||||
)
|
||||
|
||||
/*
|
||||
NewAuger returns an auger.Aug.
|
||||
|
||||
See:
|
||||
https://pkg.go.dev/honnef.co/go/augeas#readme-examples
|
||||
https://pkg.go.dev/honnef.co/go/augeas#New
|
||||
for the `root` and `loadPath` parameters
|
||||
(and, by extension, the `flags` paraemter; note that the `flags`
|
||||
is an auger.AugFlags, not an augeas.Flag!).
|
||||
|
||||
`flags` may be nil.
|
||||
*/
|
||||
func NewAuger(root, loadPath string, flags *AugFlags) (aug *Aug, err error) {
|
||||
|
||||
aug = new(Aug)
|
||||
|
||||
if aug.aug, err = augeas.New(root, loadPath, flags.Eval()); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewAugerFromAugeas returns a wrapped auger.Aug from a (honnef.co/go/augeas).Augeas.
|
||||
func NewAugerFromAugeas(orig augeas.Augeas) (aug *Aug) {
|
||||
|
||||
aug = new(Aug)
|
||||
aug.aug = orig
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
AugpathToFspath returns the filesystem path from an Augeas path.
|
||||
|
||||
It is *required* and expected that the Augeas standard /files prefix be removed first;
|
||||
if not, it is assumed to be part of the filesystem path.
|
||||
|
||||
If a valid path cannot be determined, fsPath will be empty.
|
||||
*/
|
||||
func AugpathToFspath(augPath string) (fsPath string, err error) {
|
||||
|
||||
var path string
|
||||
var num int
|
||||
var augSplit []string = strings.Split(augPath, "/")
|
||||
|
||||
num = len(augSplit)
|
||||
|
||||
for i := num - 1; i >= 0; i-- {
|
||||
path = strings.Join(augSplit[:i], "/")
|
||||
if !fs.ValidPath(path) {
|
||||
continue
|
||||
}
|
||||
if _, err = os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = nil
|
||||
continue
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fsPath = path
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// dedupePaths is used to reduce new to only unique entries that do not exist in existing.
|
||||
func dedupePaths(new, existing []string) (missing []string) {
|
||||
|
||||
var ok bool
|
||||
var m map[string]bool = make(map[string]bool)
|
||||
|
||||
for _, path := range existing {
|
||||
m[path] = true
|
||||
}
|
||||
|
||||
for _, path := range new {
|
||||
if _, ok = m[path]; !ok {
|
||||
missing = append(missing, path)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
294
auger/funcs_aug.go
Normal file
294
auger/funcs_aug.go
Normal file
@@ -0,0 +1,294 @@
|
||||
package auger
|
||||
|
||||
import (
|
||||
`bufio`
|
||||
`errors`
|
||||
`fmt`
|
||||
`io`
|
||||
`os`
|
||||
`path/filepath`
|
||||
`strings`
|
||||
|
||||
`github.com/davecgh/go-spew/spew`
|
||||
`github.com/google/shlex`
|
||||
`honnef.co/go/augeas`
|
||||
`r00t2.io/sysutils/paths`
|
||||
)
|
||||
|
||||
// Close cleanly closes the underlying Augeas connection.
|
||||
func (a *Aug) Close() {
|
||||
|
||||
a.aug.Close()
|
||||
|
||||
}
|
||||
|
||||
// Interact provides an interactive shell-like interface for debugging purposes to explore the loaded Augeas tree.
|
||||
func (a *Aug) Interact() (err error) {
|
||||
|
||||
var input string
|
||||
var lexed []string
|
||||
var cmd string
|
||||
var arg string
|
||||
var val string
|
||||
var augVal string
|
||||
var augVals []string
|
||||
var buf *bufio.Reader = bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Fprint(os.Stderr, "INTERACTIVE MODE\nCmds: get, getall, match, set, quit\n")
|
||||
breakCmd:
|
||||
for {
|
||||
cmd, arg, val = "", "", ""
|
||||
|
||||
fmt.Fprint(os.Stderr, "> ")
|
||||
if input, err = buf.ReadString('\n'); err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
err = nil
|
||||
break breakCmd
|
||||
}
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(input) == "" {
|
||||
continue
|
||||
}
|
||||
if lexed, err = shlex.Split(input); err != nil {
|
||||
return
|
||||
}
|
||||
if lexed == nil || len(lexed) == 0 || len(lexed) > 3 {
|
||||
fmt.Fprintf(os.Stderr, "Bad command: %#v\n", lexed)
|
||||
continue
|
||||
}
|
||||
cmd = lexed[0]
|
||||
switch len(lexed) {
|
||||
case 2:
|
||||
arg = lexed[1]
|
||||
case 3:
|
||||
arg = lexed[1]
|
||||
val = lexed[2]
|
||||
}
|
||||
switch cmd {
|
||||
case "get":
|
||||
if strings.TrimSpace(arg) == "" {
|
||||
fmt.Fprintln(os.Stderr, "Missing argument")
|
||||
continue
|
||||
}
|
||||
if augVal, err = a.aug.Get(arg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "!! ERROR !!\n%v\n", spew.Sdump(err))
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, augVal)
|
||||
case "getall":
|
||||
if strings.TrimSpace(arg) == "" {
|
||||
fmt.Fprintln(os.Stderr, "Missing argument")
|
||||
continue
|
||||
}
|
||||
if augVals, err = a.aug.GetAll(arg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "!! ERROR !!\n%v\n", spew.Sdump(err))
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, strings.Join(augVals, "\n"))
|
||||
case "match":
|
||||
if strings.TrimSpace(arg) == "" {
|
||||
fmt.Fprintln(os.Stderr, "Missing argument")
|
||||
continue
|
||||
}
|
||||
if augVals, err = a.aug.Match(arg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "!! ERROR !!\n%v\n", spew.Sdump(err))
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, strings.Join(augVals, "\n"))
|
||||
case "set":
|
||||
if strings.TrimSpace(arg) == "" {
|
||||
fmt.Fprintln(os.Stderr, "Missing argument")
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(val) == "" {
|
||||
fmt.Fprintln(os.Stderr, "Missing value")
|
||||
continue
|
||||
}
|
||||
if err = a.aug.Set(arg, val); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "!! ERROR !!\n%v\n", spew.Sdump(err))
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "Success!")
|
||||
case "quit":
|
||||
break breakCmd
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown command: %v\n", cmd)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
RecursiveInclude parses the configuration files belonging to Augeas lens name augLens,
|
||||
searching for all occurrences of includeDirective, loading those files (if they exist),
|
||||
and continuing so forth recursively, loading them into the Augeas file tree.
|
||||
|
||||
If any relative paths are found, they will be assumed to be relative to fsRoot ("/" if empty).
|
||||
For e.g. Nginx, you almost absolutely want to set this to "/etc/nginx", but you really should
|
||||
use absolute paths for every include in your configs if supported by the application; it will
|
||||
lead to much less guesswork and much more accurate recursing/walking.
|
||||
|
||||
Some lens recursively load depending on their respective include directive(s) automatically;
|
||||
some (such as the Nginx lens) do not.
|
||||
|
||||
For example for Nginx, augLens should be "Nginx". RecursiveInclude will then iterate over
|
||||
/augeas/load/Nginx/incl (/augeas/load/<augLens>/incl), parsing each file for includeDirective
|
||||
(the "include" keyword, in Nginx's case), check if it is already loaded in /augeas/load/<augLens>/incl,
|
||||
adding it and reloading if not, and then scanning *that* file for includeDirective, etc.
|
||||
|
||||
An error will be returned if augLens is a nonexistent or not-loaded Augeas lens module.
|
||||
|
||||
Depending on how many files there are and whether globs vs. explicit filepaths are included, this may take a while.
|
||||
*/
|
||||
func (a *Aug) RecursiveInclude(augLens, includeDirective, fsRoot string) (err error) {
|
||||
|
||||
if err = a.addIncl(includeDirective, augLens, fsRoot, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
addIncl is used by RecursiveInclude.
|
||||
|
||||
includeDirective, augLens, and fsRoot have the same meaning as in RecursiveInclude.
|
||||
|
||||
newInclPaths are new filesystem paths/Augeas-compatible glob patterns to load into the filetree and recurse into.
|
||||
They may be nil, especially if the first run.
|
||||
*/
|
||||
func (a *Aug) addIncl(includeDirective, augLens string, fsRoot string, newInclPaths []string) (err error) {
|
||||
|
||||
var matches []string // Passed around set of Augeas matches.
|
||||
var includes []string // Filepath(s)/glob(s) from fetching includeDirective in lensInclPath. These are internal to the application but are recursed.
|
||||
var lensInclPath string // The path of the included paths in the tree. These are internal to Augeas, not the application.
|
||||
var appendPath string // The path for new Augeas includes.
|
||||
var match []string // A placeholder for iterating when populating includes.
|
||||
var fpath string // A placeholder for finding the path of a conf file that contains an includeDirective.
|
||||
var lensPath string = fmt.Sprintf(augLensTpl, augLens) // The path of the lens (augLens) itself.
|
||||
var augErr *augeas.Error = new(augeas.Error) // We use this to skip "nonexistent" lens.
|
||||
|
||||
if fsRoot == "" {
|
||||
fsRoot = "/"
|
||||
}
|
||||
if err = paths.RealPath(&fsRoot); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for strings.HasSuffix(lensPath, "/") {
|
||||
lensPath = lensPath[:len(lensPath)-1]
|
||||
}
|
||||
if !strings.HasSuffix(lensPath, "/"+augInclTfm) {
|
||||
lensPath = strings.TrimSuffix(lensPath, "/"+augInclTfm)
|
||||
}
|
||||
lensInclPath = fmt.Sprintf("%v/%v", lensPath, augInclTfm)
|
||||
appendPath = fmt.Sprintf("%v/%v", lensInclPath, augAppendSuffix)
|
||||
|
||||
// First canonize paths.
|
||||
if newInclPaths != nil && len(newInclPaths) > 0 {
|
||||
// Existing includes. We don't return on an empty lensInclPath because
|
||||
if matches, err = a.aug.Match(lensInclPath); err != nil {
|
||||
if errors.As(err, augErr) && augErr.Code == augeas.NoMatch {
|
||||
err = nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
for idx, m := range matches {
|
||||
if matches[idx], err = a.aug.Get(m); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize new include(s).
|
||||
for idx, i := range newInclPaths {
|
||||
if !filepath.IsAbs(i) {
|
||||
newInclPaths[idx] = filepath.Join(fsRoot, i)
|
||||
}
|
||||
if err = paths.RealPath(&newInclPaths[idx]); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to bother adding multiple incl's for the same path(s); it can negatively affect Augeas loads.
|
||||
newInclPaths = dedupePaths(newInclPaths, matches)
|
||||
|
||||
// Add the new path(s) as Augeas include entries.
|
||||
if newInclPaths != nil {
|
||||
for _, fsPath := range newInclPaths {
|
||||
if err = a.aug.Set(appendPath, fsPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
/*
|
||||
And then load the new files into the tree.
|
||||
This is done at the end as it takes WAYYY less time to just reload the tree
|
||||
as a whole once you have more than, say, 30 files added at a time.
|
||||
*/
|
||||
if err = a.aug.Load(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We now fetch all values (filepath/globs) that match the includeDirective and recurse with those as new include files.
|
||||
matches = nil
|
||||
if includes, err = a.aug.GetAll(lensInclPath); err != nil {
|
||||
return
|
||||
}
|
||||
for _, fsPath := range includes {
|
||||
// This gets the Augeas filetree path, NOT the FS path...
|
||||
if match, err = a.aug.Match(fmt.Sprintf(augFsTpl, fsPath, includeDirective)); err != nil {
|
||||
return
|
||||
}
|
||||
if match == nil || len(match) == 0 {
|
||||
continue
|
||||
}
|
||||
/*
|
||||
For each directive match, we need to:
|
||||
|
||||
1.) normalize to an FS *file* path (strip augFsTree from the beginning
|
||||
2.) walk backwards (via AugpathToFspath) until we find an actual file
|
||||
3.) get the *dirname* of that file
|
||||
4.) join the value (included file) to #3
|
||||
IF
|
||||
fsRoot == "/"
|
||||
|
||||
This very obviously breaks for applications with arbitrary roots (like Nginx including relative to /etc/nginx).
|
||||
That's why we warn about it in Aug.RecursiveInclude. Caveat emptor.
|
||||
*/
|
||||
for idx, ftreePath := range match {
|
||||
if fpath, err = a.aug.Get(ftreePath); err != nil {
|
||||
return
|
||||
}
|
||||
if fsRoot == "/" {
|
||||
if ftreePath, err = AugpathToFspath(
|
||||
strings.TrimSuffix(ftreePath, augFsTree),
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
if ftreePath != "" {
|
||||
fpath = filepath.Join(filepath.Dir(ftreePath), fpath)
|
||||
}
|
||||
}
|
||||
match[idx] = fpath
|
||||
}
|
||||
matches = append(matches, match...)
|
||||
}
|
||||
|
||||
if matches != nil && len(matches) != 0 {
|
||||
if err = a.addIncl(includeDirective, augLens, fsRoot, matches); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
45
auger/funcs_augflags.go
Normal file
45
auger/funcs_augflags.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package auger
|
||||
|
||||
import (
|
||||
`honnef.co/go/augeas`
|
||||
)
|
||||
|
||||
// Eval returns an evaluated set of flags.
|
||||
func (a *AugFlags) Eval() (augFlags augeas.Flag) {
|
||||
|
||||
if a == nil {
|
||||
return
|
||||
}
|
||||
|
||||
augFlags = augeas.None
|
||||
|
||||
if a.Backup != nil && *a.Backup {
|
||||
augFlags |= augeas.SaveBackup
|
||||
}
|
||||
if a.NewFile != nil && *a.NewFile {
|
||||
augFlags |= augeas.SaveNewFile
|
||||
}
|
||||
if a.TypeCheck != nil && *a.TypeCheck {
|
||||
augFlags |= augeas.TypeCheck
|
||||
}
|
||||
if a.NoDfltModLoad != nil && *a.NoDfltModLoad {
|
||||
augFlags |= augeas.NoModlAutoload
|
||||
}
|
||||
if a.DryRun != nil && *a.DryRun {
|
||||
augFlags |= augeas.SaveNoop
|
||||
}
|
||||
if a.NoTree != nil && *a.NoTree {
|
||||
augFlags |= augeas.NoLoad
|
||||
}
|
||||
if a.NoAutoModLoad != nil && *a.NoAutoModLoad {
|
||||
augFlags |= augeas.NoModlAutoload
|
||||
}
|
||||
if a.EnableSpan != nil && *a.EnableSpan {
|
||||
augFlags |= augeas.EnableSpan
|
||||
}
|
||||
if a.NoErrClose != nil && *a.NoErrClose {
|
||||
augFlags |= augeas.NoErrClose
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
24
auger/funcs_test.go
Normal file
24
auger/funcs_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package auger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
`honnef.co/go/augeas`
|
||||
)
|
||||
|
||||
func TestNewAuger(t *testing.T) {
|
||||
|
||||
var aug *Aug
|
||||
var augUnder augeas.Augeas
|
||||
var err error
|
||||
|
||||
if aug, err = NewAuger("/", "", nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
augUnder = aug.aug
|
||||
|
||||
aug = NewAugerFromAugeas(augUnder)
|
||||
|
||||
_ = aug
|
||||
}
|
||||
62
auger/types.go
Normal file
62
auger/types.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package auger
|
||||
|
||||
import (
|
||||
`honnef.co/go/augeas`
|
||||
)
|
||||
|
||||
// Aug is a wrapper around (honnef.co/go/)augeas.Augeas. Remember to call Aug.Close().
|
||||
type Aug struct {
|
||||
aug augeas.Augeas
|
||||
}
|
||||
|
||||
// AugFlags contains flags to pass to the Augeas instance.
|
||||
type AugFlags struct {
|
||||
/*
|
||||
Backup, if true, will enable Augeas backup mode (original files are saved with a .augsave suffix).
|
||||
const: augeas.SaveBackup
|
||||
*/
|
||||
Backup *bool `toml:"Backup,omitempty"`
|
||||
/*
|
||||
NewFile, if true, will create new files (.augnew suffix) instead of overwriting the original file.
|
||||
const: augeas.SaveNewFile
|
||||
*/
|
||||
NewFile *bool `toml:"NewFile,omitempty"`
|
||||
/*
|
||||
TypeCheck, if true, will perform a Lens typecheck.
|
||||
HIGHLY UNRECOMMENDED; WILL INDUCE A HUGE FRONTLOAD.
|
||||
const: augeas.TypeCheck
|
||||
*/
|
||||
TypeCheck *bool `toml:"TypeCheck,omitempty"`
|
||||
/*
|
||||
NoDfltModLoad, if true, will suppress loading the built-in/default modules.
|
||||
Highly unrecommended, as we do not have a current way in the config to define load paths (yet).
|
||||
const: augeas.NoStdinc
|
||||
*/
|
||||
NoDfltModLoad *bool `toml:"NoDfltModLoad,omitempty"`
|
||||
/*
|
||||
DryRun, if true, will make all saves NO-OPs.
|
||||
const: augeas.SaveNoop
|
||||
*/
|
||||
DryRun *bool `toml:"DryRun,omitempty"`
|
||||
/*
|
||||
NoTree, if true, will not load the filetree automatically. Doesn't really affect this program.
|
||||
const: augeas.NoLoad
|
||||
*/
|
||||
NoTree *bool `toml:"NoTree,omitempty"`
|
||||
/*
|
||||
NoAutoModLoad, if true, will supress automatically loading modules.
|
||||
const: augeas.NoModlAutoload
|
||||
*/
|
||||
NoAutoModLoad *bool `toml:"NoAutoModLoad,omitempty"`
|
||||
/*
|
||||
EnableSpan, if true, will track span in input nodes (location information, essentially).
|
||||
See https://augeas.net/docs/api.html#getting-the-span-of-a-node-related-to-a-file
|
||||
const: augeas.EnableSpan
|
||||
*/
|
||||
EnableSpan *bool `toml:"EnableSpan,omitempty"`
|
||||
/*
|
||||
NoErrClose, if true, will suppress automatically closing on error.
|
||||
const: augeas.NoErrClose
|
||||
*/
|
||||
NoErrClose *bool `toml:"NoErrClose,omitempty"`
|
||||
}
|
||||
5
cryptparse/doc.go
Normal file
5
cryptparse/doc.go
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
CRYPTPARSE HAS MOVED.
|
||||
|
||||
It is now its own module: r00t2.io/cryptparse
|
||||
*/
|
||||
@@ -17,6 +17,34 @@ import (
|
||||
`r00t2.io/sysutils/paths`
|
||||
)
|
||||
|
||||
/*
|
||||
DefEnv operates like Python's .get() method on dicts (maps);
|
||||
if the environment variable specified by key does not exist/is not specified,
|
||||
then the value specified by fallback will be returned instead
|
||||
otherwise key's value is returned.
|
||||
*/
|
||||
func DefEnv(key, fallback string) (value string) {
|
||||
|
||||
var exists bool
|
||||
|
||||
if value, exists = os.LookupEnv(key); !exists {
|
||||
value = fallback
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DefEnvBlank is like DefEnv but will ADDITIONALLY/ALSO apply fallback if key is *defined/exists but is an empty string*.
|
||||
func DefEnvBlank(key, fallback string) (value string) {
|
||||
|
||||
value = DefEnv(key, fallback)
|
||||
if value == "" {
|
||||
value = fallback
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetEnvMap returns a map of all environment variables. All values are strings.
|
||||
func GetEnvMap() (envVars map[string]string) {
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
package envs
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
|
||||
14
go.mod
14
go.mod
@@ -1,18 +1,14 @@
|
||||
module r00t2.io/sysutils
|
||||
|
||||
go 1.21
|
||||
go 1.23.2
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/g0rbe/go-chattr v1.0.1
|
||||
github.com/google/uuid v1.6.0
|
||||
golang.org/x/sys v0.19.0
|
||||
r00t2.io/goutils v1.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
|
||||
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
golang.org/x/sys v0.26.0
|
||||
honnef.co/go/augeas v0.0.0-20161110001225-ca62e35ed6b8
|
||||
r00t2.io/goutils v1.7.0
|
||||
)
|
||||
|
||||
// Pending https://github.com/g0rbe/go-chattr/pull/3
|
||||
|
||||
24
go.sum
24
go.sum
@@ -1,22 +1,18 @@
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13 h1:tgEbuE4bNVjaCWWIB1u9lDzGqH/ZdBTg33+4vNW2rjg=
|
||||
github.com/johnnybubonic/go-chattr v0.0.0-20240126141003-459f46177b13/go.mod h1:yQc6VPJfpDDC1g+W2t47+yYmzBNioax/GLiyJ25/IOs=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
r00t2.io/goutils v1.4.0 h1:/x/etLpMFv3+j1aPtT7KK2G0uOk+gQkGvXIYBCdjn3E=
|
||||
r00t2.io/goutils v1.4.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||
r00t2.io/goutils v1.5.0 h1:haVk+wUK1BAk8f4UFGjy3ov3DwGMauZAOv/XYdb9isQ=
|
||||
r00t2.io/goutils v1.5.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||
r00t2.io/goutils v1.6.0 h1:oBC6PgBv0y/fdHeCmWgORHpBiU8uWw7IfFQJX5rIuzY=
|
||||
r00t2.io/goutils v1.6.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
honnef.co/go/augeas v0.0.0-20161110001225-ca62e35ed6b8 h1:FW42yWB1sGClqswyHIB68wo0+oPrav1IuQ+Tdy8Qp8E=
|
||||
honnef.co/go/augeas v0.0.0-20161110001225-ca62e35ed6b8/go.mod h1:44w9OfBSQ9l3o59rc2w3AnABtE44bmtNnRMNC7z+oKE=
|
||||
r00t2.io/goutils v1.7.0 h1:iQluWlkOyBwOKaK94D5QSnSMYpGKtMb/5WjefmdfHgI=
|
||||
r00t2.io/goutils v1.7.0/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
||||
r00t2.io/sysutils v1.7.0 h1:zk5IbcbZvq11FoXI/fLvcgyq36lBhPDY6fvC9CunfWE=
|
||||
r00t2.io/sysutils v1.7.0/go.mod h1:Sk/7riJp9fteeW9STkdQ/k22huL1J6r05n6wLh5byHY=
|
||||
|
||||
Reference in New Issue
Block a user