Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ipfs/kubo
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 348ee6448113
Choose a base ref
...
head repository: ipfs/kubo
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6adc78686989
Choose a head ref
  • 3 commits
  • 7 files changed
  • 1 contributor

Commits on Aug 4, 2015

  1. fix ipnsfs test

    License: MIT
    Signed-off-by: Jeromy <jeromyj@gmail.com>
    whyrusleeping committed Aug 4, 2015
    Copy the full SHA
    9a5f5c4 View commit details
  2. implement mfs file write

    License: MIT
    Signed-off-by: Jeromy <jeromyj@gmail.com>
    whyrusleeping committed Aug 4, 2015
    Copy the full SHA
    cc6da98 View commit details

Commits on Aug 5, 2015

  1. renaming and add some more tests

    License: MIT
    Signed-off-by: Jeromy <jeromyj@gmail.com>
    whyrusleeping committed Aug 5, 2015
    Copy the full SHA
    6adc786 View commit details
Showing with 308 additions and 39 deletions.
  1. +195 −9 core/commands/mfs.go
  2. +3 −3 core/core.go
  3. +14 −15 fuse/ipns/ipns_unix.go
  4. +1 −1 {ipnsfs → mfs}/dir.go
  5. +1 −1 {ipnsfs → mfs}/file.go
  6. +91 −7 ipnsfs/ipnsfs_test.go → mfs/mfs_test.go
  7. +3 −3 {ipnsfs → mfs}/system.go
204 changes: 195 additions & 9 deletions core/commands/mfs.go
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ import (

key "github.com/ipfs/go-ipfs/blocks/key"
cmds "github.com/ipfs/go-ipfs/commands"
mfs "github.com/ipfs/go-ipfs/ipnsfs"
dag "github.com/ipfs/go-ipfs/merkledag"
mfs "github.com/ipfs/go-ipfs/mfs"
path "github.com/ipfs/go-ipfs/path"
ft "github.com/ipfs/go-ipfs/unixfs"

@@ -59,13 +59,48 @@ on how this API could be better is very welcome.
return
}

session, found, err := req.Option("session").String()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}
if found {
// if a session is specified, print out just the root hash for that fs
root, err := node.Mfs.GetRoot(session)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

nd, err := root.GetValue().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

k, err := nd.Key()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

res.SetOutput(&mfsMountListing{[]mfs.RootListing{mfs.RootListing{Hash: k}}})
return
}

// Default: list all roots
roots := node.Mfs.ListRoots()

res.SetOutput(&mfsMountListing{roots})
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
out := res.Output().(*mfsMountListing)
if len(out.Mounts) == 1 && out.Mounts[0].Name == "" {
// a session was specified, print out just the hash
return strings.NewReader(out.Mounts[0].Hash.B58String()), nil
}

buf := new(bytes.Buffer)
for _, o := range out.Mounts {
fmt.Fprintf(buf, "%s - %s\n", o.Name, o.Hash)
@@ -78,8 +113,15 @@ on how this API could be better is very welcome.

var MfsCreateCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Create a new mutable filesystem",
ShortDescription: ``,
Tagline: "Create a new mutable filesystem",
ShortDescription: `
Creates a new mutable filesystem based on an optional root hash.
Currently, it creates a filesystem with no special publish actions,
all changes are merely propogated to the root, and are reflected in the hash
displayed by 'ipfs mfs'. In the future, this command will allow you to specify
publish actions and close actions for a given filesystem
`,
},

Arguments: []cmds.Argument{
@@ -101,6 +143,10 @@ var MfsCreateCmd = &cmds.Command{
}

name := req.Arguments()[0]
if name == "" {
res.SetError(errors.New("cannot have unnamed filesystem"), cmds.ErrNormal)
return
}

rtkey, found, err := req.Option("root").String()
if err != nil {
@@ -286,8 +332,11 @@ var MfsLsCmd = &cmds.Command{

var MfsPutCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "import a given file into a filesystem",
ShortDescription: ``,
Tagline: "import a given file into a filesystem",
ShortDescription: `
Mfs 'put' takes a file that already exists in ipfs and imports it into a
given mfs filesystem.
`,
},

Arguments: []cmds.Argument{
@@ -362,8 +411,11 @@ func PutNodeUnderRoot(root *mfs.Root, ipath string, nd *dag.Node) error {

var MfsReadCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Read a file in a given mfs",
ShortDescription: ``,
Tagline: "Read a file in a given mfs",
ShortDescription: `
Read a specified number of bytes from a file at a given offset. By default, will
read the entire file similar to unix cat.
`,
},

Arguments: []cmds.Argument{
@@ -431,8 +483,15 @@ var MfsReadCmd = &cmds.Command{

var MfsMvCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Move files",
ShortDescription: ``,
Tagline: "Move files",
ShortDescription: `
Move files around. Just like traditional unix mv.
Example:
ipfs mfs -s myfs mv /a/b/c /foo/newc
`,
},

Arguments: []cmds.Argument{
@@ -519,6 +578,133 @@ var MfsMvCmd = &cmds.Command{
},
}

var MfsWriteCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Write to a mutable file in a given filesystem",
ShortDescription: `
Write data to a file in a given filesystem. This command allows you to specify
a beginning offset to write to. The entire length of the input will be written.
If the '--create' option is specified, the file will be create if it does not
exist. Nonexistant intermediate directories will not be created.
Example:
echo "hello world" | ipfs mfs -s myfs --create /a/b/file
`,
},
Arguments: []cmds.Argument{
cmds.StringArg("path", true, false, "path to write to"),
cmds.FileArg("data", true, false, "data to write").EnableStdin(),
},
Options: []cmds.Option{
cmds.IntOption("o", "offset", "offset to write to"),
cmds.BoolOption("c", "create", "create the file if it does not exist"),
},
Run: func(req cmds.Request, res cmds.Response) {
node, err := req.InvocContext().GetNode()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

if node.Mfs == nil {
res.SetError(errNotOnline, cmds.ErrNormal)
return
}

sess, err := getSession(req.Option("session"))
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

root, err := node.Mfs.GetRoot(sess)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

path := req.Arguments()[0]
create, _, _ := req.Option("create").Bool()

fi, err := getFileHandle(root, path, create)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

offset, _, _ := req.Option("offset").Int()

_, err = fi.Seek(int64(offset), os.SEEK_SET)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

input, err := req.Files().NextFile()
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

n, err := io.Copy(fi, input)
if err != nil {
res.SetError(err, cmds.ErrNormal)
return
}

log.Debugf("wrote %d bytes to %s", n, path)
},
}

func getFileHandle(root *mfs.Root, path string, create bool) (*mfs.File, error) {
dir := root.GetValue().(*mfs.Directory)

target, err := mfs.DirLookup(dir, path)
switch err {
case nil:
fi, ok := target.(*mfs.File)
if !ok {
return nil, fmt.Errorf("%s was not a file", path)
}
return fi, nil

case os.ErrNotExist:
if !create {
return nil, err
}

// if create is specified and the file doesnt exist, we create the file
dirname, fname := gopath.Split(path)
pdiri, err := mfs.DirLookup(dir, dirname)
if err != nil {
return nil, err
}
pdir, ok := pdiri.(*mfs.Directory)
if !ok {
return nil, fmt.Errorf("%s was not a directory", dirname)
}

nd := &dag.Node{Data: ft.FilePBData(nil, 0)}
err = pdir.AddChild(fname, nd)
if err != nil {
return nil, err
}

fsn, err := pdir.Child(fname)
if err != nil {
return nil, err
}

// can unsafely cast, if it fails, that means programmer error
return fsn.(*mfs.File), nil

default:
return nil, err
}
}

var MfsCmdTemplate = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Manipulate mutable filesystems",
6 changes: 3 additions & 3 deletions core/core.go
Original file line number Diff line number Diff line change
@@ -50,8 +50,8 @@ import (
rp "github.com/ipfs/go-ipfs/exchange/reprovide"

mount "github.com/ipfs/go-ipfs/fuse/mount"
ipnsfs "github.com/ipfs/go-ipfs/ipnsfs"
merkledag "github.com/ipfs/go-ipfs/merkledag"
mfs "github.com/ipfs/go-ipfs/mfs"
namesys "github.com/ipfs/go-ipfs/namesys"
path "github.com/ipfs/go-ipfs/path"
pin "github.com/ipfs/go-ipfs/pin"
@@ -106,7 +106,7 @@ type IpfsNode struct {
Ping *ping.PingService
Reprovider *rp.Reprovider // the value reprovider system

Mfs *ipnsfs.Filesystem
Mfs *mfs.Filesystem

proc goprocess.Process
ctx context.Context
@@ -164,7 +164,7 @@ func NewIPFSNode(ctx context.Context, option ConfigOption) (*IpfsNode, error) {

// Setup the mutable ipns filesystem structure
if node.OnlineMode() {
fs, err := ipnsfs.NewFilesystem(ctx, node.DAG, node.Pinning)
fs, err := mfs.NewFilesystem(ctx, node.DAG, node.Pinning)
if err != nil && err != kb.ErrLookupFailure {
return nil, err
}
29 changes: 14 additions & 15 deletions fuse/ipns/ipns_unix.go
Original file line number Diff line number Diff line change
@@ -17,9 +17,8 @@ import (

key "github.com/ipfs/go-ipfs/blocks/key"
core "github.com/ipfs/go-ipfs/core"
mfs "github.com/ipfs/go-ipfs/ipnsfs"
nsfs "github.com/ipfs/go-ipfs/ipnsfs"
dag "github.com/ipfs/go-ipfs/merkledag"
mfs "github.com/ipfs/go-ipfs/mfs"
ci "github.com/ipfs/go-ipfs/p2p/crypto"
path "github.com/ipfs/go-ipfs/path"
ft "github.com/ipfs/go-ipfs/unixfs"
@@ -74,7 +73,7 @@ type Root struct {
LocalDirs map[string]fs.Node
Roots map[string]*keyRoot

fs *nsfs.Filesystem
fs *mfs.Filesystem
LocalLinks map[string]*Link
}

@@ -117,9 +116,9 @@ func (r *Root) loadRoot(ctx context.Context, name string) (*mfs.Root, error) {
rt.root = root

switch val := root.GetValue().(type) {
case *nsfs.Directory:
case *mfs.Directory:
r.LocalDirs[name] = &Directory{dir: val}
case *nsfs.File:
case *mfs.File:
r.LocalDirs[name] = &File{fi: val}
default:
return nil, errors.New("unrecognized type")
@@ -268,16 +267,16 @@ func (r *Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
return listing, nil
}

// Directory is wrapper over an ipnsfs directory to satisfy the fuse fs interface
// Directory is wrapper over an mfs directory to satisfy the fuse fs interface
type Directory struct {
dir *nsfs.Directory
dir *mfs.Directory

fs.NodeRef
}

// File is wrapper over an ipnsfs file to satisfy the fuse fs interface
// File is wrapper over an mfs file to satisfy the fuse fs interface
type File struct {
fi *nsfs.File
fi *mfs.File

fs.NodeRef
}
@@ -319,9 +318,9 @@ func (s *Directory) Lookup(ctx context.Context, name string) (fs.Node, error) {
}

switch child := child.(type) {
case *nsfs.Directory:
case *mfs.Directory:
return &Directory{dir: child}, nil
case *nsfs.File:
case *mfs.File:
return &File{fi: child}, nil
default:
// NB: if this happens, we do not want to continue, unpredictable behaviour
@@ -340,10 +339,10 @@ func (dir *Directory) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
for _, entry := range listing {
dirent := fuse.Dirent{Name: entry.Name}

switch nsfs.NodeType(entry.Type) {
case nsfs.TDir:
switch mfs.NodeType(entry.Type) {
case mfs.TDir:
dirent.Type = fuse.DT_Dir
case nsfs.TFile:
case mfs.TFile:
dirent.Type = fuse.DT_File
}

@@ -485,7 +484,7 @@ func (dir *Directory) Create(ctx context.Context, req *fuse.CreateRequest, resp
return nil, nil, err
}

fi, ok := child.(*nsfs.File)
fi, ok := child.(*mfs.File)
if !ok {
return nil, nil, errors.New("child creation failed")
}
2 changes: 1 addition & 1 deletion ipnsfs/dir.go → mfs/dir.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ipnsfs
package mfs

import (
"errors"
2 changes: 1 addition & 1 deletion ipnsfs/file.go → mfs/file.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ipnsfs
package mfs

import (
"sync"
Loading