@cryptotaxi247 / kubo / commits / 889f73e90

Add 'ipfs repo migrate' command (#8428)

* Add 'ipfs repo migrate' command This PR replaces #7658 that was originally contributed by zaibons, in order to move code into a branch and avoid some CI problem. The command allows the user to run the repo migration without starting the daemon. resolves #7471 * return non-ErrNeedMigration errors from fsrepo.Open() Co-authored-by: Gus Eggert <gus@gus.dev>

Andrew Gillis committed May 6, 2022 at 14:34 UTC 889f73e90e55cc17c7c434d1a21c9e091deed626
4 files changed +111 -6
core/commands/commands_test.go
+1
@@ -217,6 +217,7 @@ func TestCommands(t *testing.T) {
217 "/repo",
218 "/repo/fsck",
219 "/repo/gc",
220 + "/repo/migrate",
221 "/repo/stat",
222 "/repo/verify",
223 "/repo/version",
core/commands/repo.go
+72 -4
@@ -11,11 +11,14 @@ import (
11 "sync"
12 "text/tabwriter"
13
14 - humanize "github.com/dustin/go-humanize"
14 + oldcmds "github.com/ipfs/go-ipfs/commands"
15 cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
16 corerepo "github.com/ipfs/go-ipfs/core/corerepo"
17 fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
18 + "github.com/ipfs/go-ipfs/repo/fsrepo/migrations"
19 + "github.com/ipfs/go-ipfs/repo/fsrepo/migrations/ipfsfetcher"
20
21 + humanize "github.com/dustin/go-humanize"
22 cid "github.com/ipfs/go-cid"
23 bstore "github.com/ipfs/go-ipfs-blockstore"
24 cmds "github.com/ipfs/go-ipfs-cmds"
@@ -39,6 +42,7 @@ var RepoCmd = &cmds.Command{
42 "fsck": repoFsckCmd,
43 "version": repoVersionCmd,
44 "verify": repoVerifyCmd,
45 + "migrate": repoMigrateCmd,
46 },
47 }
48
@@ -49,9 +53,10 @@ type GcResult struct {
53 }
54
55 const (
52 - repoStreamErrorsOptionName = "stream-errors"
53 - repoQuietOptionName = "quiet"
54 - repoSilentOptionName = "silent"
56 + repoStreamErrorsOptionName = "stream-errors"
57 + repoQuietOptionName = "quiet"
58 + repoSilentOptionName = "silent"
59 + repoAllowDowngradeOptionName = "allow-downgrade"
60 )
61
62 var repoGcCmd = &cmds.Command{
@@ -387,3 +392,66 @@ var repoVersionCmd = &cmds.Command{
392 }),
393 },
394 }
395 +
396 +var repoMigrateCmd = &cmds.Command{
397 + Helptext: cmds.HelpText{
398 + Tagline: "Apply any outstanding migrations to the repo.",
399 + },
400 + Options: []cmds.Option{
401 + cmds.BoolOption(repoAllowDowngradeOptionName, "Allow downgrading to a lower repo version"),
402 + },
403 + NoRemote: true,
404 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
405 + cctx := env.(*oldcmds.Context)
406 + allowDowngrade, _ := req.Options[repoAllowDowngradeOptionName].(bool)
407 +
408 + _, err := fsrepo.Open(cctx.ConfigRoot)
409 +
410 + if err == nil {
411 + fmt.Println("Repo does not require migration.")
412 + return nil
413 + } else if err != fsrepo.ErrNeedMigration {
414 + return err
415 + }
416 +
417 + fmt.Println("Found outdated fs-repo, starting migration.")
418 +
419 + // Read Migration section of IPFS config
420 + configFileOpt, _ := req.Options[ConfigFileOption].(string)
421 + migrationCfg, err := migrations.ReadMigrationConfig(cctx.ConfigRoot, configFileOpt)
422 + if err != nil {
423 + return err
424 + }
425 +
426 + // Define function to create IPFS fetcher. Do not supply an
427 + // already-constructed IPFS fetcher, because this may be expensive and
428 + // not needed according to migration config. Instead, supply a function
429 + // to construct the particular IPFS fetcher implementation used here,
430 + // which is called only if an IPFS fetcher is needed.
431 + newIpfsFetcher := func(distPath string) migrations.Fetcher {
432 + return ipfsfetcher.NewIpfsFetcher(distPath, 0, &cctx.ConfigRoot, configFileOpt)
433 + }
434 +
435 + // Fetch migrations from current distribution, or location from environ
436 + fetchDistPath := migrations.GetDistPathEnv(migrations.CurrentIpfsDist)
437 +
438 + // Create fetchers according to migrationCfg.DownloadSources
439 + fetcher, err := migrations.GetMigrationFetcher(migrationCfg.DownloadSources, fetchDistPath, newIpfsFetcher)
440 + if err != nil {
441 + return err
442 + }
443 + defer fetcher.Close()
444 +
445 + err = migrations.RunMigration(cctx.Context(), fetcher, fsrepo.RepoVersion, "", allowDowngrade)
446 + if err != nil {
447 + fmt.Println("The migrations of fs-repo failed:")
448 + fmt.Printf(" %s\n", err)
449 + fmt.Println("If you think this is a bug, please file an issue and include this whole log output.")
450 + fmt.Println(" https://github.com/ipfs/fs-repo-migrations")
451 + return err
452 + }
453 +
454 + fmt.Printf("Success: fs-repo has been migrated to version %d.\n", fsrepo.RepoVersion)
455 + return nil
456 + },
457 +}
repo/fsrepo/migrations/ipfsfetcher/ipfsfetcher.go
-2
@@ -247,8 +247,6 @@ func (f *IpfsFetcher) startTempNode(ctx context.Context) error {
247 cancel()
248 // Wait until ipfs is stopped
249 <-node.Context().Done()
250 -
251 - fmt.Println("migration peer", node.Identity, "shutdown")
250 }
251
252 addrs, err := ipfs.Swarm().LocalAddrs(ctx)
test/sharness/t0066-migration.sh
+38
@@ -84,4 +84,42 @@ test_expect_success "output looks good" '
84 grep "Please get fs-repo-migrations from https://dist.ipfs.io" daemon_out > /dev/null
85 '
86
87 +test_expect_success "ipfs repo migrate succeed" '
88 + test_expect_code 0 ipfs repo migrate > migrate_out
89 +'
90 +
91 +test_expect_success "output looks good" '
92 + grep "Found outdated fs-repo, starting migration." migrate_out > /dev/null &&
93 + grep "Success: fs-repo migrated to version $IPFS_REPO_VER" true_out > /dev/null
94 +'
95 +
96 +test_expect_success "manually reset repo version to latest" '
97 + echo "$IPFS_REPO_VER" > "$IPFS_PATH"/version
98 +'
99 +
100 +test_expect_success "detect repo does not need migration" '
101 + test_expect_code 0 ipfs repo migrate > migrate_out
102 +'
103 +
104 +test_expect_success "output looks good" '
105 + grep "Repo does not require migration" migrate_out > /dev/null
106 +'
107 +
108 +# ensure that we get a lock error if we need to migrate and the daemon is running
109 +test_launch_ipfs_daemon
110 +
111 +test_expect_success "manually reset repo version to $MIGRATION_START" '
112 + echo "$MIGRATION_START" > "$IPFS_PATH"/version
113 +'
114 +
115 +test_expect_success "ipfs repo migrate fails" '
116 + test_expect_code 1 ipfs repo migrate 2> migrate_out
117 +'
118 +
119 +test_expect_success "output looks good" '
120 + grep "repo.lock" migrate_out > /dev/null
121 +'
122 +
123 +test_kill_ipfs_daemon
124 +
125 test_done