Skip to content

Commit

Permalink
chore: stop using go-homedir (#10568)
Browse files Browse the repository at this point in the history
* chore: stop using go-homedir

The `github.com/mitchellh/go-homedir` repo is archived, no longer needed, and no longer maintained.

- `homedir.Dir` is replaced by the stdlib `os.UserHomeDir`
- `homedir.Expand` is replaced by fsutil.ExpandHome` in the `github.com/ipfs/kubo/misc/fsutil` package.

Additional functionality, such as `DirWritable` and `FileExists` was moved into or included in the `github.com/ipfs/kubo/misc/fsutil` package.
  • Loading branch information
gammazero authored Nov 5, 2024
1 parent e17dc21 commit 4009ad3
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 94 deletions.
4 changes: 2 additions & 2 deletions client/rpc/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import (
ipfs "github.com/ipfs/kubo"
iface "github.com/ipfs/kubo/core/coreiface"
caopts "github.com/ipfs/kubo/core/coreiface/options"
"github.com/ipfs/kubo/misc/fsutil"
dagpb "github.com/ipld/go-codec-dagpb"
_ "github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/node/basicnode"
"github.com/mitchellh/go-homedir"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)
Expand Down Expand Up @@ -82,7 +82,7 @@ func NewPathApi(ipfspath string) (*HttpApi, error) {

// ApiAddr reads api file in specified ipfs path.
func ApiAddr(ipfspath string) (ma.Multiaddr, error) {
baseDir, err := homedir.Expand(ipfspath)
baseDir, err := fsutil.ExpandHome(ipfspath)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/ipfswatch/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import (
core "github.com/ipfs/kubo/core"
coreapi "github.com/ipfs/kubo/core/coreapi"
corehttp "github.com/ipfs/kubo/core/corehttp"
"github.com/ipfs/kubo/misc/fsutil"
fsrepo "github.com/ipfs/kubo/repo/fsrepo"

fsnotify "github.com/fsnotify/fsnotify"
"github.com/ipfs/boxo/files"
process "github.com/jbenet/goprocess"
homedir "github.com/mitchellh/go-homedir"
)

var (
Expand Down Expand Up @@ -57,7 +57,7 @@ func run(ipfsPath, watchPath string) error {
proc := process.WithParent(process.Background())
log.Printf("running IPFSWatch on '%s' using repo at '%s'...", watchPath, ipfsPath)

ipfsPath, err := homedir.Expand(ipfsPath)
ipfsPath, err := fsutil.ExpandHome(ipfsPath)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"path/filepath"
"strings"

"github.com/mitchellh/go-homedir"
"github.com/ipfs/kubo/misc/fsutil"
)

// Config is used to load ipfs config files.
Expand Down Expand Up @@ -59,7 +59,7 @@ func PathRoot() (string, error) {
dir := os.Getenv(EnvDir)
var err error
if len(dir) == 0 {
dir, err = homedir.Expand(DefaultPathRoot)
dir, err = fsutil.ExpandHome(DefaultPathRoot)
}
return dir, err
}
Expand Down
9 changes: 9 additions & 0 deletions docs/changelogs/v0.32.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [🔦 Highlights](#-highlights)
- [🎯 AutoTLS: Automatic Certificates for libp2p WebSockets via `libp2p.direct`](#-autotls-automatic-certificates-for-libp2p-websockets-via-libp2pdirect)
- [📦️ Boxo and go-libp2p updates](#-boxo-and-go-libp2p-updates)
- [Replaced dependency on archived `github.com/mitchellh/go-homedir`](replaced-go-homedir)
- [📝 Changelog](#-changelog)
- [👨‍👩‍👧‍👦 Contributors](#-contributors)

Expand All @@ -31,6 +32,14 @@ See [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls)
- update `go-libp2p-kad-dht` to [v0.27.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.27.0)
- update `go-libp2p-pubsub` to [v0.12.0](https://github.com/libp2p/go-libp2p-pubsub/releases/tag/v0.12.0)

### Replaced go-homedir

The `github.com/mitchellh/go-homedir` repo is archived, no longer needed, and no longer maintained.

- `homedir.Dir` is replaced by the stdlib `os.UserHomeDir`
- `homedir.Expand` is replaced by `fsutil.ExpandHome` in the `github.com/ipfs/kubo/misc/fsutil` package.
- The new `github.com/ipfs/kubo/misc/fsutil` package contains file utility code previously located elsewhere in kubo.

### 📝 Changelog

### 👨‍👩‍👧‍👦 Contributors
1 change: 0 additions & 1 deletion docs/examples/kubo-as-a-library/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ require (
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
Expand Down
1 change: 0 additions & 1 deletion docs/examples/kubo-as-a-library/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ require (
github.com/libp2p/go-libp2p-routing-helpers v0.7.4
github.com/libp2p/go-libp2p-testing v0.12.0
github.com/libp2p/go-socket-activation v0.1.0
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.13.0
github.com/multiformats/go-multiaddr-dns v0.4.0
github.com/multiformats/go-multibase v0.2.0
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
82 changes: 82 additions & 0 deletions misc/fsutil/fsutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package fsutil

import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
)

// DirWritable checks if a directory is writable. If the directory does
// not exist it is created with writable permission.
func DirWritable(dir string) error {
if dir == "" {
return errors.New("directory not specified")
}

var err error
dir, err = ExpandHome(dir)
if err != nil {
return err
}

fi, err := os.Stat(dir)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// Directory does not exist, so create it.
err = os.Mkdir(dir, 0775)
if err == nil {
return nil
}
}
if errors.Is(err, fs.ErrPermission) {
err = fs.ErrPermission
}
return fmt.Errorf("directory not writable: %s: %w", dir, err)
}
if !fi.IsDir() {
return fmt.Errorf("not a directory: %s", dir)
}

// Directory exists, check that a file can be written.
file, err := os.CreateTemp(dir, "writetest")
if err != nil {
if errors.Is(err, fs.ErrPermission) {
err = fs.ErrPermission
}
return fmt.Errorf("directory not writable: %s: %w", dir, err)
}
file.Close()
return os.Remove(file.Name())
}

// ExpandHome expands the path to include the home directory if the path is
// prefixed with `~`. If it isn't prefixed with `~`, the path is returned
// as-is.
func ExpandHome(path string) (string, error) {
if path == "" {
return path, nil
}

if path[0] != '~' {
return path, nil
}

if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
return "", errors.New("cannot expand user-specific home dir")
}

dir, err := os.UserHomeDir()
if err != nil {
return "", err
}

return filepath.Join(dir, path[1:]), nil
}

// FileExists return true if the file exists
func FileExists(filename string) bool {
_, err := os.Lstat(filename)
return !errors.Is(err, os.ErrNotExist)
}
92 changes: 92 additions & 0 deletions misc/fsutil/fsutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package fsutil_test

import (
"io/fs"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/ipfs/kubo/misc/fsutil"
"github.com/stretchr/testify/require"
)

func TestDirWritable(t *testing.T) {
err := fsutil.DirWritable("")
require.Error(t, err)

err = fsutil.DirWritable("~nosuchuser/tmp")
require.Error(t, err)

tmpDir := t.TempDir()

wrDir := filepath.Join(tmpDir, "readwrite")
err = fsutil.DirWritable(wrDir)
require.NoError(t, err)

// Check that DirWritable created directory.
fi, err := os.Stat(wrDir)
require.NoError(t, err)
require.True(t, fi.IsDir())

err = fsutil.DirWritable(wrDir)
require.NoError(t, err)

// If running on Windows, skip read-only directory tests.
if runtime.GOOS == "windows" {
t.SkipNow()
}

roDir := filepath.Join(tmpDir, "readonly")
require.NoError(t, os.Mkdir(roDir, 0500))
err = fsutil.DirWritable(roDir)
require.ErrorIs(t, err, fs.ErrPermission)

roChild := filepath.Join(roDir, "child")
err = fsutil.DirWritable(roChild)
require.ErrorIs(t, err, fs.ErrPermission)
}

func TestFileExists(t *testing.T) {
fileName := filepath.Join(t.TempDir(), "somefile")
require.False(t, fsutil.FileExists(fileName))

file, err := os.Create(fileName)
require.NoError(t, err)
file.Close()

require.True(t, fsutil.FileExists(fileName))
}

func TestExpandHome(t *testing.T) {
dir, err := fsutil.ExpandHome("")
require.NoError(t, err)
require.Equal(t, "", dir)

origDir := filepath.Join("somedir", "somesub")
dir, err = fsutil.ExpandHome(origDir)
require.NoError(t, err)
require.Equal(t, origDir, dir)

_, err = fsutil.ExpandHome(filepath.FromSlash("~nosuchuser/somedir"))
require.Error(t, err)

homeEnv := "HOME"
if runtime.GOOS == "windows" {
homeEnv = "USERPROFILE"
}
origHome := os.Getenv(homeEnv)
defer os.Setenv(homeEnv, origHome)
homeDir := filepath.Join(t.TempDir(), "testhome")
os.Setenv(homeEnv, homeDir)

const subDir = "mytmp"
origDir = filepath.Join("~", subDir)
dir, err = fsutil.ExpandHome(origDir)
require.NoError(t, err)
require.Equal(t, filepath.Join(homeDir, subDir), dir)

os.Unsetenv(homeEnv)
_, err = fsutil.ExpandHome(origDir)
require.Error(t, err)
}
72 changes: 2 additions & 70 deletions plugin/plugins/pebbleds/pebbleds.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package pebbleds

import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"time"

"github.com/cockroachdb/pebble"
pebbleds "github.com/ipfs/go-ds-pebble"
"github.com/ipfs/kubo/misc/fsutil"
"github.com/ipfs/kubo/plugin"
"github.com/ipfs/kubo/repo"
"github.com/ipfs/kubo/repo/fsrepo"
Expand Down Expand Up @@ -172,75 +170,9 @@ func (c *datastoreConfig) Create(path string) (repo.Datastore, error) {
p = filepath.Join(path, p)
}

if err := dirWritable(p); err != nil {
if err := fsutil.DirWritable(p); err != nil {
return nil, err
}

return pebbleds.NewDatastore(p, pebbleds.WithCacheSize(c.cacheSize), pebbleds.WithPebbleOpts(c.pebbleOpts))
}

// dirWritable checks if a directory is writable. If the directory does
// not exist it is created with writable permission.
func dirWritable(dir string) error {
if dir == "" {
return errors.New("directory not specified")
}
var err error
dir, err = expandHome(dir)
if err != nil {
return err
}

fi, err := os.Stat(dir)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// Directory does not exist, so create it.
err = os.Mkdir(dir, 0775)
if err == nil {
return nil
}
}
if errors.Is(err, fs.ErrPermission) {
err = fs.ErrPermission
}
return fmt.Errorf("directory not writable: %s: %w", dir, err)
}
if !fi.IsDir() {
return fmt.Errorf("not a directory: %s", dir)
}

// Directory exists, check that a file can be written.
file, err := os.CreateTemp(dir, "writetest")
if err != nil {
if errors.Is(err, fs.ErrPermission) {
err = fs.ErrPermission
}
return fmt.Errorf("directory not writable: %s: %w", dir, err)
}
file.Close()
return os.Remove(file.Name())
}

// expandHome expands the path to include the home directory if the path is
// prefixed with `~`. If it isn't prefixed with `~`, the path is returned
// as-is.
func expandHome(path string) (string, error) {
if path == "" {
return path, nil
}

if path[0] != '~' {
return path, nil
}

if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
return "", errors.New("cannot expand user-specific home dir")
}

dir, err := os.UserHomeDir()
if err != nil {
return "", err
}

return filepath.Join(dir, path[1:]), nil
}
Loading

0 comments on commit 4009ad3

Please sign in to comment.