Commit 1b74100e authored by Levin Zimmermann's avatar Levin Zimmermann Committed by Kirill Smelkov

go/neo/interal += xpath, xfilepath

The xfilepath package supports resolving filepaths with a user prefix
to absolute paths: it converts '~' and '~username' to $HOME of user
(as it's done by for  instance bash). No builtin golang module supports this
functionality [1]. We need this functionality in order to imitate the
behaviour of NEO/py in NEO/go [2].

---

[1] https://stackoverflow.com/questions/47261719/how-can-i-resolve-a-relative-path-to-absolute-path-in-golang)
[2] nexedi/slapos!1307 (comment 17574)

/reviewed-by @kirr
/reviewed-on !1
parent 789c9ed9
// Copyright (C) 2023 Nexedi SA and Contributors
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
// Package xfilepath provides addons to std package filepath.
package xfilepath
import (
"os/user"
path_ "path"
"strings"
)
// ExpandUser does '~' and '~username' expansion.
//
// It resolves '~' into the $HOME directory of current user
// and '~user' into the $HOME directory of 'user'.
//
// If the provided path doesn't start with '~', ExpandUser returns the path
// without any changes.
//
// ExpandUser does NOT support bashs '~+' and '~-' prefix (for '$PWD' and '$OLDPWD')
// and it does NOT support bashs '~N', '~+N' and '~-N' prefix.
//
// Please see here for bash tilde expansion documentation:
// https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
func ExpandUser(path string) string {
if strings.HasPrefix(path, "~") {
s := strings.SplitN(path[1:], "/", 2)
if home, err := homeOf(s[0]); err == nil {
var remainder string
if len(s) > 1 { remainder = s[1] }
return path_.Join(home, remainder)
}
// We ignore any error returned by 'homeOf' and simply
// return path as it is.
// We do so to be compatible with the behaviour of bash and
// of pythons 'os.path.expanduser' function.
}
return path
}
// homeOf returns $HOME of user with given username.
// If username is an empty string (e.g. ""), homeOf returns
// $HOME of the current user.
func homeOf(username string) (string, error) {
usr, err := lookupUser(username)
if err != nil {
return "", err
}
return usr.HomeDir, nil
}
// lookupUser returns User with username.
//
// If username is an empty string (""), lookupUser
// returns the current user.
func lookupUser(username string) (*user.User, error) {
if username == "" {
return user.Current()
} else {
return user.Lookup(username)
}
}
// Copyright (C) 2023 Nexedi SA and Contributors.
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package xfilepath
import (
"os/user"
"testing"
"lab.nexedi.com/kirr/neo/go/internal/xtesting"
)
func TestExpandUser(t *testing.T) {
X := xtesting.FatalIf(t)
xhomeOf := func(username string) string {
t.Helper()
home, err := homeOf(username); X(err)
return home
}
home := xhomeOf("")
homeRoot := xhomeOf("root")
me, err := user.Current(); X(err)
testv := []struct{ path, expandOk string }{
{"", ""},
{"~", home},
{"~/", home},
{"~" + me.Username, home},
{"~/abc", home + "/abc"},
{"~root/", homeRoot},
{"~root", homeRoot},
{"abc/", "abc/"},
{"abc/~", "abc/~"},
{"/abc/", "/abc/"},
}
for _, tCase := range testv {
expanded := ExpandUser(tCase.path)
if expanded != tCase.expandOk {
t.Errorf("%s -> %s ; want %s", tCase.path, expanded, tCase.expandOk)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment