Пример #1
0
func GetMigrations() (string, error) {
	latest, err := GetLatestVersion(util.IpfsVersionPath, migrations)
	if err != nil {
		return "", fmt.Errorf("getting latest version of fs-repo-migrations: %s", err)
	}

	dir, err := ioutil.TempDir("", "ipfs-update-migrate")
	if err != nil {
		return "", fmt.Errorf("tempdir: %s", err)
	}

	out := filepath.Join(dir, migrations)

	err = GetBinaryForVersion(migrations, migrations, util.IpfsVersionPath, latest, out)
	if err != nil {
		stump.Error("getting migrations binary: %s", err)

		stump.Log("could not find or install fs-repo-migrations, please manually install it")
		stump.Log("before running ipfs-update again.")
		return "", fmt.Errorf("failed to find migrations binary")
	}

	err = os.Chmod(out, 0755)
	if err != nil {
		return "", err
	}

	return out, nil
}
Пример #2
0
func (i *Install) Run() error {
	defer i.RevertOnFailure()

	var err error
	i.CurrentVers, err = GetCurrentVersion()
	if err != nil {
		return err
	}

	if i.CurrentVers == "none" {
		stump.VLog("no pre-existing ipfs installation found")
	} else if i.CurrentVers == i.TargetVers {
		stump.Log("Already have version %s installed, skipping.", i.TargetVers)
		i.Succeeded = true
		return nil
	}

	err = i.DownloadNewBinary()
	if err != nil {
		return err
	}

	if !i.NoCheck {
		stump.Log("binary downloaded, verifying...")
		err = test.TestBinary(i.TmpBinPath, i.TargetVers)
		if err != nil {
			return err
		}
	} else {
		stump.Log("skipping tests since '--no-check' was passed")
	}

	err = i.MaybeStash()
	if err != nil {
		return err
	}

	err = i.SelectGoodInstallLoc()
	if err != nil {
		return err
	}

	stump.Log("installing new binary to %s", i.InstallPath)
	err = InstallBinaryTo(i.TmpBinPath, i.InstallPath)
	if err != nil {
		// in case of error here, replace old binary
		stump.Error("Install failed: ", err)

		return err
	}

	err = i.postInstallMigrationCheck()
	if err != nil {
		stump.Error("Migration Failed: ", err)
		return err
	}

	i.Succeeded = true
	return nil
}
Пример #3
0
func RunMigration(oldv, newv string) error {
	migrateBin := "fs-repo-migrations"
	stump.VLog("  - checking for migrations binary...")
	_, err := exec.LookPath(migrateBin)
	if err != nil {
		stump.VLog("  - migrations not found on system, attempting to install")
		loc, err := GetMigrations()
		if err != nil {
			return err
		}

		migrateBin = loc
	}

	// check to make sure migrations binary supports our target version
	err = verifyMigrationSupportsVersion(migrateBin, newv)
	if err != nil {
		return err
	}

	cmd := exec.Command(migrateBin, "-to", newv, "-y")

	cmd.Stdout = stump.LogOut
	cmd.Stderr = stump.ErrOut

	stump.Log("running migration: '%s -to %s -y'", migrateBin, newv)

	err = cmd.Run()
	if err != nil {
		return fmt.Errorf("migration failed: %s", err)
	}

	stump.Log("migration succeeded!")
	return nil
}
Пример #4
0
func revertOldBinary(oldpath, version string) {
	stashpath := filepath.Join(util.IpfsDir(), "old-bin", "ipfs-"+version)
	rnerr := util.Move(stashpath, oldpath)
	if rnerr != nil {
		stump.Log("Error reverting")
		stump.Log("failed to replace binary after install fail: ", rnerr)
		stump.Log("sorry :(")
		stump.Log("your old ipfs binary should still be located at: ", stashpath)
		stump.Log("try: `mv %q %q`", stashpath, oldpath)
	}
}
Пример #5
0
func selectRevertBin() (string, error) {
	oldbinpath := filepath.Join(util.IpfsDir(), "old-bin")
	_, err := os.Stat(oldbinpath)
	if os.IsNotExist(err) {
		return "", fmt.Errorf("No prior binary found at: %s", oldbinpath)
	}

	entries, err := ioutil.ReadDir(oldbinpath)
	if err != nil {
		return "", err
	}

	for i, e := range entries {
		if e.Name() == "path-old" {
			entries = append(entries[:i], entries[i+1:]...)
			break
		}
	}

	switch len(entries) {
	case 0:
		return "", fmt.Errorf("no prior binary found")
	case 1:
		return filepath.Join(oldbinpath, entries[0].Name()), nil
	default:
	}

	stump.Log("found multiple old binaries:")
	tw := tabwriter.NewWriter(stump.LogOut, 6, 4, 4, ' ', 0)
	for i, bin := range entries {
		fmt.Fprintf(tw, "%d)\t%s\t%s\n", i+1, bin.Name(), bin.ModTime().Format(time.ANSIC))
	}
	tw.Flush()

	stump.Log("install which? (0 to exit)")
	scan := bufio.NewScanner(os.Stdin)
	for scan.Scan() {
		n, err := strconv.Atoi(scan.Text())
		if n == 0 {
			return "", fmt.Errorf("exiting at user request")
		}
		if err != nil || n < 1 || n > len(entries) {
			stump.Log("please enter a number in the range 1-%d (0 to exit)", len(entries))
			continue
		}

		stump.Log("installing %s...", entries[n-1].Name())
		return filepath.Join(oldbinpath, entries[n-1].Name()), nil
	}
	return "", fmt.Errorf("failed to select binary")
}
Пример #6
0
func (i *Install) MaybeStash() error {
	if i.CurrentVers != "none" {
		stump.Log("stashing old binary")
		oldpath, err := StashOldBinary(i.CurrentVers, false)
		if err != nil {
			if strings.Contains(err.Error(), "could not find old") {
				stump.Log("stash failed, no binary found.")
				stump.Log(util.BoldText("this could be because you have a daemon running, but no ipfs binary in your path."))
				stump.Log("continuing anyways, but skipping stash")
				return nil
			}
			return err
		}
		i.StashedFromPath = filepath.Dir(oldpath)
	} else {
		stump.VLog("skipping stash, no previous install")
	}

	return nil
}
Пример #7
0
func (i *Install) RevertOnFailure() {
	if i.Succeeded {
		return
	}

	stump.Log("install failed, reverting changes...")

	if i.CurrentVers != "none" && i.InstallPath != "" {
		revertOldBinary(i.InstallPath, i.CurrentVers)
	}
}
Пример #8
0
func GetBinaryForVersion(distname, binnom, root, vers, out string) error {
	stump.Log("fetching %s version %s", distname, vers)
	dir, err := ioutil.TempDir("", "ipfs-update")
	if err != nil {
		return err
	}

	stump.VLog("  - using GOOS=%s and GOARCH=%s", runtime.GOOS, runtime.GOARCH)
	var archive string
	switch runtime.GOOS {
	case "windows":
		archive = "zip"
	default:
		archive = "tar.gz"
	}
	finame := fmt.Sprintf("%s_%s_%s-%s.%s", distname, vers, runtime.GOOS, runtime.GOARCH, archive)

	distpath := fmt.Sprintf("%s/%s/%s/%s", root, distname, vers, finame)

	data, err := util.Fetch(distpath)
	if err != nil {
		return err
	}

	arcpath := filepath.Join(dir, finame)
	fi, err := os.Create(arcpath)
	if err != nil {
		return err
	}

	stump.VLog("  - writing to", arcpath)
	_, err = io.Copy(fi, data)
	if err != nil {
		return err
	}
	fi.Close()

	return unpackArchive(distname, binnom, arcpath, out, archive)
}
Пример #9
0
func CheckMigration() error {
	stump.Log("checking if repo migration is needed...")
	p := util.IpfsDir()

	vfilePath := filepath.Join(p, "version")
	_, err := os.Stat(vfilePath)
	if os.IsNotExist(err) {
		stump.VLog("  - no prexisting repo to migrate")
		return nil
	}

	oldverB, err := ioutil.ReadFile(vfilePath)
	if err != nil {
		return err
	}

	oldver := strings.Trim(string(oldverB), "\n \t")
	stump.VLog("  - old repo version is", oldver)

	nbinver, err := util.RunCmd("", "ipfs", "version", "--repo")
	if err != nil {
		stump.Log("Failed to check new binary repo version.")
		stump.VLog("Reason: ", err)
		stump.Log("This is not an error.")
		stump.Log("This just means that you may have to manually run the migration")
		stump.Log("You will be prompted to do so upon starting the ipfs daemon if necessary")
		return nil
	}

	stump.VLog("  - repo version of new binary is ", nbinver)

	if oldver != nbinver {
		stump.Log("  check complete, migration required.")
		return RunMigration(oldver, nbinver)
	}

	stump.VLog("  check complete, no migration required.")

	return nil
}
Пример #10
0
func TestBinary(bin, version string) error {
	_, err := os.Stat(bin)
	if err != nil {
		return err
	}

	// make sure binary is executable
	err = os.Chmod(bin, 0755)
	if err != nil {
		return err
	}

	staging := filepath.Join(util.IpfsDir(), "update-staging")
	err = os.MkdirAll(staging, 0755)
	if err != nil {
		return fmt.Errorf("error creating test staging directory: %s", err)
	}

	tdir, err := ioutil.TempDir(staging, "test")
	if err != nil {
		return err
	}

	err = os.MkdirAll(tdir, 0755)
	if err != nil {
		return fmt.Errorf("error creating test staging directory: %s", err)
	}

	defer func(dir string) {
		// defer cleanup, bound param to avoid mistakes
		err = os.RemoveAll(dir)
		if err != nil {
			stump.Error("error cleaning up staging directory: ", err)
		}
	}(tdir)

	stump.VLog("  - running init in '%s' with new binary", tdir)
	_, err = runCmd(tdir, bin, "init")
	if err != nil {
		return fmt.Errorf("error initializing with new binary: %s", err)
	}

	stump.VLog("  - checking new binary outputs correct version")
	rversion, err := runCmd(tdir, bin, "version")
	if err != nil {
		return err
	}

	parts := strings.Fields(rversion)
	if !versionMatch(parts[len(parts)-1], version[1:]) {
		return fmt.Errorf("version didnt match")
	}

	if util.BeforeVersion("v0.3.8", version) {
		stump.Log("== skipping tests with daemon, versions before 0.3.8 do not support port zero ==")
		return nil
	}

	// set up ports in config so we dont interfere with an already running daemon
	stump.VLog("  - tweaking test config to avoid external interference")
	err = tweakConfig(tdir)
	if err != nil {
		return err
	}

	stump.VLog("  - starting up daemon")
	daemon, err := StartDaemon(tdir, bin)
	if err != nil {
		return fmt.Errorf("error starting daemon: %s", err)
	}
	defer func() {
		stump.VLog("  - killing test daemon")
		err := daemon.Close()
		if err != nil {
			stump.VLog("  - error killing test daemon: %s (continuing anyway)", err)
		}
		stump.Log("success!")
	}()

	// test some basic things against the daemon
	err = testFileAdd(tdir, bin)
	if err != nil {
		return fmt.Errorf("test file add: %s", err)
	}

	err = testRefsList(tdir, bin)
	if err != nil {
		return fmt.Errorf("test refs list: %s", err)
	}

	return nil
}
Пример #11
0
		if !strings.HasPrefix(vers, "v") && looksLikeSemver(vers) {
			stump.VLog("Version strings must start with 'v'. Autocorrecting...")
			vers = "v" + vers
		}

		i, err := NewInstall(util.IpfsVersionPath, vers, c.Bool("no-check"))
		if err != nil {
			return err
		}

		err = i.Run()
		if err != nil {
			return err
		}
		stump.Log("\nInstallation complete!")

		if util.HasDaemonRunning() {
			stump.Log("Remember to restart your daemon before continuing.")
		}

		return nil
	},
}

var cmdStash = cli.Command{
	Name:  "stash",
	Usage: "stashes copy of currently installed ipfs binary",
	Description: `'stash' is an advanced command that saves the currently installed
   version of ipfs to a backup location. This is useful when you want to experiment
   with different versions, but still be able to go back to the version you started with.`,