chore: stop using go-homedir (#10568)
* 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. (cherry picked from commit 4009ad3e5a502518ddc7d48a888707f812ddc629)
Andrew Gillis committed
Nov 5, 2024 at 05:45 UTC
c53f3c552da77f078f08f945d2f306c36d25f3ee
14 files changed
+200
-94
client/rpc/api.go
+2
-2
@@ -20,10 +20,10 @@ import (
20
ipfs "github.com/ipfs/kubo"
21
iface "github.com/ipfs/kubo/core/coreiface"
22
caopts "github.com/ipfs/kubo/core/coreiface/options"
23
+ "github.com/ipfs/kubo/misc/fsutil"
24
dagpb "github.com/ipld/go-codec-dagpb"
25
_ "github.com/ipld/go-ipld-prime/codec/dagcbor"
26
"github.com/ipld/go-ipld-prime/node/basicnode"
26
- "github.com/mitchellh/go-homedir"
27
ma "github.com/multiformats/go-multiaddr"
28
manet "github.com/multiformats/go-multiaddr/net"
29
)
@@ -82,7 +82,7 @@ func NewPathApi(ipfspath string) (*HttpApi, error) {
82
83
// ApiAddr reads api file in specified ipfs path.
84
func ApiAddr(ipfspath string) (ma.Multiaddr, error) {
85
- baseDir, err := homedir.Expand(ipfspath)
85
+ baseDir, err := fsutil.ExpandHome(ipfspath)
86
if err != nil {
87
return nil, err
88
}
cmd/ipfswatch/main.go
+2
-2
@@ -16,12 +16,12 @@ import (
16
core "github.com/ipfs/kubo/core"
17
coreapi "github.com/ipfs/kubo/core/coreapi"
18
corehttp "github.com/ipfs/kubo/core/corehttp"
19
+ "github.com/ipfs/kubo/misc/fsutil"
20
fsrepo "github.com/ipfs/kubo/repo/fsrepo"
21
22
fsnotify "github.com/fsnotify/fsnotify"
23
"github.com/ipfs/boxo/files"
24
process "github.com/jbenet/goprocess"
24
- homedir "github.com/mitchellh/go-homedir"
25
)
26
27
var (
@@ -57,7 +57,7 @@ func run(ipfsPath, watchPath string) error {
57
proc := process.WithParent(process.Background())
58
log.Printf("running IPFSWatch on '%s' using repo at '%s'...", watchPath, ipfsPath)
59
60
- ipfsPath, err := homedir.Expand(ipfsPath)
60
+ ipfsPath, err := fsutil.ExpandHome(ipfsPath)
61
if err != nil {
62
return err
63
}
config/config.go
+2
-2
@@ -9,7 +9,7 @@ import (
9
"path/filepath"
10
"strings"
11
12
- "github.com/mitchellh/go-homedir"
12
+ "github.com/ipfs/kubo/misc/fsutil"
13
)
14
15
// Config is used to load ipfs config files.
@@ -59,7 +59,7 @@ func PathRoot() (string, error) {
59
dir := os.Getenv(EnvDir)
60
var err error
61
if len(dir) == 0 {
62
- dir, err = homedir.Expand(DefaultPathRoot)
62
+ dir, err = fsutil.ExpandHome(DefaultPathRoot)
63
}
64
return dir, err
65
}
docs/changelogs/v0.32.md
+9
@@ -8,6 +8,7 @@
8
- [🔦 Highlights](#-highlights)
9
- [🎯 AutoTLS: Automatic Certificates for libp2p WebSockets via `libp2p.direct`](#-autotls-automatic-certificates-for-libp2p-websockets-via-libp2pdirect)
10
- [📦️ Boxo and go-libp2p updates](#-boxo-and-go-libp2p-updates)
11
+ - [Replaced dependency on archived `github.com/mitchellh/go-homedir`](replaced-go-homedir)
12
- [📝 Changelog](#-changelog)
13
- [👨👩👧👦 Contributors](#-contributors)
14
@@ -31,6 +32,14 @@ See [`AutoTLS`](https://github.com/ipfs/kubo/blob/master/docs/config.md#autotls)
32
- update `go-libp2p-kad-dht` to [v0.27.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.27.0)
33
- update `go-libp2p-pubsub` to [v0.12.0](https://github.com/libp2p/go-libp2p-pubsub/releases/tag/v0.12.0)
34
35
+### Replaced go-homedir
36
+
37
+The `github.com/mitchellh/go-homedir` repo is archived, no longer needed, and no longer maintained.
38
+
39
+- `homedir.Dir` is replaced by the stdlib `os.UserHomeDir`
40
+- `homedir.Expand` is replaced by `fsutil.ExpandHome` in the `github.com/ipfs/kubo/misc/fsutil` package.
41
+- The new `github.com/ipfs/kubo/misc/fsutil` package contains file utility code previously located elsewhere in kubo.
42
+
43
### 📝 Changelog
44
45
### 👨👩👧👦 Contributors
docs/examples/kubo-as-a-library/go.mod
-1
@@ -144,7 +144,6 @@ require (
144
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
145
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
146
github.com/minio/sha256-simd v1.0.1 // indirect
147
- github.com/mitchellh/go-homedir v1.1.0 // indirect
147
github.com/mr-tron/base58 v1.2.0 // indirect
148
github.com/multiformats/go-base32 v0.1.0 // indirect
149
github.com/multiformats/go-base36 v0.2.0 // indirect
docs/examples/kubo-as-a-library/go.sum
-1
@@ -535,7 +535,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
535
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
536
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
537
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
538
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
538
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
539
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
540
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
go.mod
-1
@@ -64,7 +64,6 @@ require (
64
github.com/libp2p/go-libp2p-routing-helpers v0.7.4
65
github.com/libp2p/go-libp2p-testing v0.12.0
66
github.com/libp2p/go-socket-activation v0.1.0
67
- github.com/mitchellh/go-homedir v1.1.0
67
github.com/multiformats/go-multiaddr v0.13.0
68
github.com/multiformats/go-multiaddr-dns v0.4.0
69
github.com/multiformats/go-multibase v0.2.0
go.sum
-1
@@ -629,7 +629,6 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
629
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
630
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
631
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
632
-github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
632
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
633
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
634
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
misc/fsutil/fsutil.go
new
+82
@@ -0,0 +1,82 @@
1
+package fsutil
2
+
3
+import (
4
+ "errors"
5
+ "fmt"
6
+ "io/fs"
7
+ "os"
8
+ "path/filepath"
9
+)
10
+
11
+// DirWritable checks if a directory is writable. If the directory does
12
+// not exist it is created with writable permission.
13
+func DirWritable(dir string) error {
14
+ if dir == "" {
15
+ return errors.New("directory not specified")
16
+ }
17
+
18
+ var err error
19
+ dir, err = ExpandHome(dir)
20
+ if err != nil {
21
+ return err
22
+ }
23
+
24
+ fi, err := os.Stat(dir)
25
+ if err != nil {
26
+ if errors.Is(err, fs.ErrNotExist) {
27
+ // Directory does not exist, so create it.
28
+ err = os.Mkdir(dir, 0775)
29
+ if err == nil {
30
+ return nil
31
+ }
32
+ }
33
+ if errors.Is(err, fs.ErrPermission) {
34
+ err = fs.ErrPermission
35
+ }
36
+ return fmt.Errorf("directory not writable: %s: %w", dir, err)
37
+ }
38
+ if !fi.IsDir() {
39
+ return fmt.Errorf("not a directory: %s", dir)
40
+ }
41
+
42
+ // Directory exists, check that a file can be written.
43
+ file, err := os.CreateTemp(dir, "writetest")
44
+ if err != nil {
45
+ if errors.Is(err, fs.ErrPermission) {
46
+ err = fs.ErrPermission
47
+ }
48
+ return fmt.Errorf("directory not writable: %s: %w", dir, err)
49
+ }
50
+ file.Close()
51
+ return os.Remove(file.Name())
52
+}
53
+
54
+// ExpandHome expands the path to include the home directory if the path is
55
+// prefixed with `~`. If it isn't prefixed with `~`, the path is returned
56
+// as-is.
57
+func ExpandHome(path string) (string, error) {
58
+ if path == "" {
59
+ return path, nil
60
+ }
61
+
62
+ if path[0] != '~' {
63
+ return path, nil
64
+ }
65
+
66
+ if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
67
+ return "", errors.New("cannot expand user-specific home dir")
68
+ }
69
+
70
+ dir, err := os.UserHomeDir()
71
+ if err != nil {
72
+ return "", err
73
+ }
74
+
75
+ return filepath.Join(dir, path[1:]), nil
76
+}
77
+
78
+// FileExists return true if the file exists
79
+func FileExists(filename string) bool {
80
+ _, err := os.Lstat(filename)
81
+ return !errors.Is(err, os.ErrNotExist)
82
+}
misc/fsutil/fsutil_test.go
new
+92
@@ -0,0 +1,92 @@
1
+package fsutil_test
2
+
3
+import (
4
+ "io/fs"
5
+ "os"
6
+ "path/filepath"
7
+ "runtime"
8
+ "testing"
9
+
10
+ "github.com/ipfs/kubo/misc/fsutil"
11
+ "github.com/stretchr/testify/require"
12
+)
13
+
14
+func TestDirWritable(t *testing.T) {
15
+ err := fsutil.DirWritable("")
16
+ require.Error(t, err)
17
+
18
+ err = fsutil.DirWritable("~nosuchuser/tmp")
19
+ require.Error(t, err)
20
+
21
+ tmpDir := t.TempDir()
22
+
23
+ wrDir := filepath.Join(tmpDir, "readwrite")
24
+ err = fsutil.DirWritable(wrDir)
25
+ require.NoError(t, err)
26
+
27
+ // Check that DirWritable created directory.
28
+ fi, err := os.Stat(wrDir)
29
+ require.NoError(t, err)
30
+ require.True(t, fi.IsDir())
31
+
32
+ err = fsutil.DirWritable(wrDir)
33
+ require.NoError(t, err)
34
+
35
+ // If running on Windows, skip read-only directory tests.
36
+ if runtime.GOOS == "windows" {
37
+ t.SkipNow()
38
+ }
39
+
40
+ roDir := filepath.Join(tmpDir, "readonly")
41
+ require.NoError(t, os.Mkdir(roDir, 0500))
42
+ err = fsutil.DirWritable(roDir)
43
+ require.ErrorIs(t, err, fs.ErrPermission)
44
+
45
+ roChild := filepath.Join(roDir, "child")
46
+ err = fsutil.DirWritable(roChild)
47
+ require.ErrorIs(t, err, fs.ErrPermission)
48
+}
49
+
50
+func TestFileExists(t *testing.T) {
51
+ fileName := filepath.Join(t.TempDir(), "somefile")
52
+ require.False(t, fsutil.FileExists(fileName))
53
+
54
+ file, err := os.Create(fileName)
55
+ require.NoError(t, err)
56
+ file.Close()
57
+
58
+ require.True(t, fsutil.FileExists(fileName))
59
+}
60
+
61
+func TestExpandHome(t *testing.T) {
62
+ dir, err := fsutil.ExpandHome("")
63
+ require.NoError(t, err)
64
+ require.Equal(t, "", dir)
65
+
66
+ origDir := filepath.Join("somedir", "somesub")
67
+ dir, err = fsutil.ExpandHome(origDir)
68
+ require.NoError(t, err)
69
+ require.Equal(t, origDir, dir)
70
+
71
+ _, err = fsutil.ExpandHome(filepath.FromSlash("~nosuchuser/somedir"))
72
+ require.Error(t, err)
73
+
74
+ homeEnv := "HOME"
75
+ if runtime.GOOS == "windows" {
76
+ homeEnv = "USERPROFILE"
77
+ }
78
+ origHome := os.Getenv(homeEnv)
79
+ defer os.Setenv(homeEnv, origHome)
80
+ homeDir := filepath.Join(t.TempDir(), "testhome")
81
+ os.Setenv(homeEnv, homeDir)
82
+
83
+ const subDir = "mytmp"
84
+ origDir = filepath.Join("~", subDir)
85
+ dir, err = fsutil.ExpandHome(origDir)
86
+ require.NoError(t, err)
87
+ require.Equal(t, filepath.Join(homeDir, subDir), dir)
88
+
89
+ os.Unsetenv(homeEnv)
90
+ _, err = fsutil.ExpandHome(origDir)
91
+ require.Error(t, err)
92
+}
plugin/plugins/pebbleds/pebbleds.go
+2
-70
@@ -1,15 +1,13 @@
1
package pebbleds
2
3
import (
4
- "errors"
4
"fmt"
6
- "io/fs"
7
- "os"
5
"path/filepath"
6
"time"
7
8
"github.com/cockroachdb/pebble"
9
pebbleds "github.com/ipfs/go-ds-pebble"
10
+ "github.com/ipfs/kubo/misc/fsutil"
11
"github.com/ipfs/kubo/plugin"
12
"github.com/ipfs/kubo/repo"
13
"github.com/ipfs/kubo/repo/fsrepo"
@@ -172,75 +170,9 @@ func (c *datastoreConfig) Create(path string) (repo.Datastore, error) {
170
p = filepath.Join(path, p)
171
}
172
175
- if err := dirWritable(p); err != nil {
173
+ if err := fsutil.DirWritable(p); err != nil {
174
return nil, err
175
}
176
177
return pebbleds.NewDatastore(p, pebbleds.WithCacheSize(c.cacheSize), pebbleds.WithPebbleOpts(c.pebbleOpts))
178
}
181
-
182
-// dirWritable checks if a directory is writable. If the directory does
183
-// not exist it is created with writable permission.
184
-func dirWritable(dir string) error {
185
- if dir == "" {
186
- return errors.New("directory not specified")
187
- }
188
- var err error
189
- dir, err = expandHome(dir)
190
- if err != nil {
191
- return err
192
- }
193
-
194
- fi, err := os.Stat(dir)
195
- if err != nil {
196
- if errors.Is(err, fs.ErrNotExist) {
197
- // Directory does not exist, so create it.
198
- err = os.Mkdir(dir, 0775)
199
- if err == nil {
200
- return nil
201
- }
202
- }
203
- if errors.Is(err, fs.ErrPermission) {
204
- err = fs.ErrPermission
205
- }
206
- return fmt.Errorf("directory not writable: %s: %w", dir, err)
207
- }
208
- if !fi.IsDir() {
209
- return fmt.Errorf("not a directory: %s", dir)
210
- }
211
-
212
- // Directory exists, check that a file can be written.
213
- file, err := os.CreateTemp(dir, "writetest")
214
- if err != nil {
215
- if errors.Is(err, fs.ErrPermission) {
216
- err = fs.ErrPermission
217
- }
218
- return fmt.Errorf("directory not writable: %s: %w", dir, err)
219
- }
220
- file.Close()
221
- return os.Remove(file.Name())
222
-}
223
-
224
-// expandHome expands the path to include the home directory if the path is
225
-// prefixed with `~`. If it isn't prefixed with `~`, the path is returned
226
-// as-is.
227
-func expandHome(path string) (string, error) {
228
- if path == "" {
229
- return path, nil
230
- }
231
-
232
- if path[0] != '~' {
233
- return path, nil
234
- }
235
-
236
- if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
237
- return "", errors.New("cannot expand user-specific home dir")
238
- }
239
-
240
- dir, err := os.UserHomeDir()
241
- if err != nil {
242
- return "", err
243
- }
244
-
245
- return filepath.Join(dir, path[1:]), nil
246
-}
repo/fsrepo/fsrepo.go
+4
-5
@@ -18,15 +18,14 @@ import (
18
dir "github.com/ipfs/kubo/thirdparty/dir"
19
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
20
21
- util "github.com/ipfs/boxo/util"
21
ds "github.com/ipfs/go-datastore"
22
measure "github.com/ipfs/go-ds-measure"
23
lockfile "github.com/ipfs/go-fs-lock"
24
logging "github.com/ipfs/go-log"
25
config "github.com/ipfs/kubo/config"
26
serialize "github.com/ipfs/kubo/config/serialize"
27
+ "github.com/ipfs/kubo/misc/fsutil"
28
"github.com/ipfs/kubo/repo/fsrepo/migrations"
29
- homedir "github.com/mitchellh/go-homedir"
29
ma "github.com/multiformats/go-multiaddr"
30
)
31
@@ -207,7 +206,7 @@ func open(repoPath string, userConfigFilePath string) (repo.Repo, error) {
206
}
207
208
func newFSRepo(rpath string, userConfigFilePath string) (*FSRepo, error) {
210
- expPath, err := homedir.Expand(filepath.Clean(rpath))
209
+ expPath, err := fsutil.ExpandHome(filepath.Clean(rpath))
210
if err != nil {
211
return nil, err
212
}
@@ -239,7 +238,7 @@ func configIsInitialized(path string) bool {
238
if err != nil {
239
return false
240
}
242
- if !util.FileExists(configFilename) {
241
+ if !fsutil.FileExists(configFilename) {
242
return false
243
}
244
return true
@@ -269,7 +268,7 @@ func initSpec(path string, conf map[string]interface{}) error {
268
return err
269
}
270
272
- if util.FileExists(fn) {
271
+ if fsutil.FileExists(fn) {
272
return nil
273
}
274
repo/fsrepo/migrations/ipfsdir.go
+3
-7
@@ -8,7 +8,7 @@ import (
8
"strconv"
9
"strings"
10
11
- "github.com/mitchellh/go-homedir"
11
+ "github.com/ipfs/kubo/misc/fsutil"
12
)
13
14
const (
@@ -17,10 +17,6 @@ const (
17
versionFile = "version"
18
)
19
20
-func init() {
21
- homedir.DisableCache = true
22
-}
23
-
20
// IpfsDir returns the path of the ipfs directory. If dir specified, then
21
// returns the expanded version dir. If dir is "", then return the directory
22
// set by IPFS_PATH, or if IPFS_PATH is not set, then return the default
@@ -31,14 +27,14 @@ func IpfsDir(dir string) (string, error) {
27
dir = os.Getenv(envIpfsPath)
28
}
29
if dir != "" {
34
- dir, err = homedir.Expand(dir)
30
+ dir, err = fsutil.ExpandHome(dir)
31
if err != nil {
32
return "", err
33
}
34
return dir, nil
35
}
36
41
- home, err := homedir.Dir()
37
+ home, err := os.UserHomeDir()
38
if err != nil {
39
return "", err
40
}
repo/fsrepo/misc.go
+2
-2
@@ -4,7 +4,7 @@ import (
4
"os"
5
6
config "github.com/ipfs/kubo/config"
7
- homedir "github.com/mitchellh/go-homedir"
7
+ "github.com/ipfs/kubo/misc/fsutil"
8
)
9
10
// BestKnownPath returns the best known fsrepo path. If the ENV override is
@@ -15,7 +15,7 @@ func BestKnownPath() (string, error) {
15
if os.Getenv(config.EnvDir) != "" {
16
ipfsPath = os.Getenv(config.EnvDir)
17
}
18
- ipfsPath, err := homedir.Expand(ipfsPath)
18
+ ipfsPath, err := fsutil.ExpandHome(ipfsPath)
19
if err != nil {
20
return "", err
21
}