init.go 4.45 KB
Newer Older
1
package main
Matt Bell's avatar
Matt Bell committed
2 3

import (
4
	"bytes"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
5
	"fmt"
Matt Bell's avatar
Matt Bell committed
6

7
	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
Matt Bell's avatar
Matt Bell committed
8
	cmds "github.com/jbenet/go-ipfs/commands"
9
	core "github.com/jbenet/go-ipfs/core"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
10
	coreunix "github.com/jbenet/go-ipfs/core/coreunix"
Jeromy's avatar
Jeromy committed
11
	ipns "github.com/jbenet/go-ipfs/fuse/ipns"
12
	config "github.com/jbenet/go-ipfs/repo/config"
13
	fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
Matt Bell's avatar
Matt Bell committed
14
	u "github.com/jbenet/go-ipfs/util"
15
	debugerror "github.com/jbenet/go-ipfs/util/debugerror"
Matt Bell's avatar
Matt Bell committed
16 17
)

18 19
const nBitsForKeypairDefault = 4096

Matt Bell's avatar
Matt Bell committed
20
var initCmd = &cmds.Command{
21 22 23 24
	Helptext: cmds.HelpText{
		Tagline:          "Initializes IPFS config file",
		ShortDescription: "Initializes IPFS configuration files and generates a new keypair.",
	},
25

Matt Bell's avatar
Matt Bell committed
26
	Options: []cmds.Option{
27
		cmds.IntOption("bits", "b", "Number of bits to use in the generated RSA private key (defaults to 4096)"),
28 29
		cmds.StringOption("passphrase", "p", "Passphrase for encrypting the private key"),
		cmds.BoolOption("force", "f", "Overwrite existing config (if it exists)"),
30 31 32 33 34

		// TODO need to decide whether to expose the override as a file or a
		// directory. That is: should we allow the user to also specify the
		// name of the file?
		// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
Matt Bell's avatar
Matt Bell committed
35
	},
36
	Run: func(req cmds.Request, res cmds.Response) {
37

38
		force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
39
		if err != nil {
40 41
			res.SetError(err, cmds.ErrNormal)
			return
42 43
		}

44
		nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
45
		if err != nil {
46 47
			res.SetError(err, cmds.ErrNormal)
			return
48
		}
49
		if !bitsOptFound {
50
			nBitsForKeypair = nBitsForKeypairDefault
51 52
		}

53 54 55 56 57 58
		output, err := doInit(req.Context().ConfigRoot, force, nBitsForKeypair)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		res.SetOutput(output)
59 60
	},
}
Matt Bell's avatar
Matt Bell committed
61

62
var errRepoExists = debugerror.New(`ipfs configuration file already exists!
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
Reinitializing would overwrite your keys.
(use -f to force overwrite)
`)

var welcomeMsg = `Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

`

81 82
func initWithDefaults(repoRoot string) error {
	_, err := doInit(repoRoot, false, nBitsForKeypairDefault)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
83
	return debugerror.Wrap(err)
84 85
}

86 87
func doInit(repoRoot string, force bool, nBitsForKeypair int) (interface{}, error) {
	u.POut("initializing ipfs node at %s\n", repoRoot)
88

89
	if fsrepo.IsInitialized(repoRoot) && !force {
90
		return nil, errRepoExists
91
	}
92
	conf, err := config.Init(nBitsForKeypair)
93
	if err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
94
		return nil, err
95
	}
96
	if fsrepo.IsInitialized(repoRoot) {
97 98 99
		if err := fsrepo.Remove(repoRoot); err != nil {
			return nil, err
		}
100
	}
101 102 103
	if err := fsrepo.Init(repoRoot, conf); err != nil {
		return nil, err
	}
104

105
	err = addTheWelcomeFile(repoRoot)
106 107 108
	if err != nil {
		return nil, err
	}
Jeromy's avatar
Jeromy committed
109 110 111 112
	err = initializeIpnsKeyspace(repoRoot)
	if err != nil {
		return nil, err
	}
113 114 115 116
	return nil, nil
}

// addTheWelcomeFile adds a file containing the welcome message to the newly
117
// minted node.
118
func addTheWelcomeFile(repoRoot string) error {
119
	ctx, cancel := context.WithCancel(context.Background())
120 121 122 123 124 125
	defer cancel()
	r := fsrepo.At(repoRoot)
	if err := r.Open(); err != nil { // NB: repo is owned by the node
		return err
	}
	nd, err := core.NewIPFSNode(ctx, core.Offline(r))
126
	if err != nil {
127
		return err
128 129 130 131
	}
	defer nd.Close()

	// Set up default file
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
132
	reader := bytes.NewBufferString(welcomeMsg)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
133
	k, err := coreunix.Add(nd, reader)
134
	if err != nil {
135
		return fmt.Errorf("failed to write test file: %s", err)
136
	}
Brian Tiger Chow's avatar
fix  
Brian Tiger Chow committed
137
	fmt.Printf("\nto get started, enter: ipfs cat %s\n", k)
138
	return nil
Matt Bell's avatar
Matt Bell committed
139
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
140

Jeromy's avatar
Jeromy committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
func initializeIpnsKeyspace(repoRoot string) error {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	r := fsrepo.At(repoRoot)
	if err := r.Open(); err != nil { // NB: repo is owned by the node
		return err
	}

	nd, err := core.NewIPFSNode(ctx, core.Offline(r))
	if err != nil {
		return err
	}
	defer nd.Close()

	err = nd.SetupOfflineRouting()
	if err != nil {
		return err
	}

	return ipns.InitializeKeyspace(nd, nd.PrivateKey)
}