Skip to content

Commit

Permalink
Allow mfs files.write command to create parent directories
Browse files Browse the repository at this point in the history
Adds support for a `-p/--parents` flag to the `files.write` command
similar to the one supported by the `files.mkdir` command. If this
is true and the directory for the file is not `"/"`, try to create
the containing directory before writing to the file.

License: MIT
Signed-off-by: Alex Potsides <[email protected]>
  • Loading branch information
achingbrain committed Aug 14, 2018
1 parent 0e5ed59 commit c97c44e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
23 changes: 23 additions & 0 deletions core/commands/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ stat' on the file or any of its ancestors.
Options: []cmdkit.Option{
cmdkit.IntOption("offset", "o", "Byte offset to begin writing at."),
cmdkit.BoolOption("create", "e", "Create the file if it does not exist."),
cmdkit.BoolOption("parents", "p", "Make parent directories as needed."),
cmdkit.BoolOption("truncate", "t", "Truncate the file to size zero before writing."),
cmdkit.IntOption("count", "n", "Maximum number of bytes to read."),
cmdkit.BoolOption("raw-leaves", "Use raw blocks for newly created leaf nodes. (experimental)"),
Expand All @@ -735,6 +736,7 @@ stat' on the file or any of its ancestors.
}

create, _ := req.Options["create"].(bool)
mkParents, _ := req.Options["parents"].(bool)
trunc, _ := req.Options["truncate"].(bool)
flush, _ := req.Options["flush"].(bool)
rawLeaves, rawLeavesDef := req.Options["raw-leaves"].(bool)
Expand All @@ -757,6 +759,14 @@ stat' on the file or any of its ancestors.
return
}

if mkParents {
err := ensureContainingDirectoryExists(nd.FilesRoot, path, prefix)
if err != nil {
re.SetError(err, cmdkit.ErrNormal)
return
}
}

fi, err := getFileHandle(nd.FilesRoot, path, create, prefix)
if err != nil {
re.SetError(err, cmdkit.ErrNormal)
Expand Down Expand Up @@ -1146,6 +1156,19 @@ func getPrefix(req oldcmds.Request) (cid.Builder, error) {
return &prefix, nil
}

func ensureContainingDirectoryExists(r *mfs.Root, path string, builder cid.Builder) error {
dirtomake := gopath.Dir(path)

if dirtomake == "/" {
return nil
}

return mfs.Mkdir(r, dirtomake, mfs.MkdirOpts{
Mkparents: true,
CidBuilder: builder,
})
}

func getFileHandle(r *mfs.Root, path string, create bool, builder cid.Builder) (*mfs.File, error) {
target, err := mfs.Lookup(r, path)
switch err {
Expand Down
22 changes: 21 additions & 1 deletion test/sharness/t0250-files-api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -597,9 +597,29 @@ test_files_api() {
ipfs files ls /adir | grep foobar
'

test_expect_success "should fail to write file and create intermediate directories with no --parents flag set $EXTRA" '
echo "ipfs rocks" | test_must_fail ipfs files write --create /parents/foo/ipfs.txt
'

test_expect_success "can write file and create intermediate directories $EXTRA" '
echo "ipfs rocks" | ipfs files write --create --parents /parents/foo/bar/baz/ipfs.txt &&
ipfs files stat "/parents/foo/bar/baz/ipfs.txt" | grep -q "^Type: file"
'

test_expect_success "can write file and create intermediate directories with short flags $EXTRA" '
echo "ipfs rocks" | ipfs files write -e -p /parents/foo/bar/baz/qux/quux/garply/ipfs.txt &&
ipfs files stat "/parents/foo/bar/baz/qux/quux/garply/ipfs.txt" | grep -q "^Type: file"
'

test_expect_success "can write another file in the same directory with -e -p $EXTRA" '
echo "ipfs rocks" | ipfs files write -e -p /parents/foo/bar/baz/qux/quux/garply/ipfs2.txt &&
ipfs files stat "/parents/foo/bar/baz/qux/quux/garply/ipfs2.txt" | grep -q "^Type: file"
'

test_expect_success "clean up $EXTRA" '
ipfs files rm -r /foobar &&
ipfs files rm -r /adir
ipfs files rm -r /adir &&
ipfs files rm -r /parents
'

test_expect_success "root mfs entry is empty $EXTRA" '
Expand Down

0 comments on commit c97c44e

Please sign in to comment.