github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfstool/mkdir.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "flag" 9 "fmt" 10 "os" 11 12 "github.com/keybase/client/go/kbfs/data" 13 "github.com/keybase/client/go/kbfs/fsrpc" 14 "github.com/keybase/client/go/kbfs/libkbfs" 15 "golang.org/x/net/context" 16 ) 17 18 func maybePrintPath(path string, err error, verbose bool) { 19 if err == nil && verbose { 20 fmt.Fprintf(os.Stderr, "mkdir: created directory %q\n", path) 21 } 22 } 23 24 func createDir(ctx context.Context, kbfsOps libkbfs.KBFSOps, parentNode libkbfs.Node, dirname, path string, verbose bool) (libkbfs.Node, error) { 25 childNode, _, err := kbfsOps.CreateDir( 26 ctx, parentNode, parentNode.ChildName(dirname)) 27 maybePrintPath(path, err, verbose) 28 return childNode, err 29 } 30 31 func mkdirOne(ctx context.Context, config libkbfs.Config, dirPathStr string, createIntermediate, verbose bool) error { 32 p, err := fsrpc.NewPath(dirPathStr) 33 if err != nil { 34 return err 35 } 36 37 kbfsOps := config.KBFSOps() 38 39 if createIntermediate { 40 if p.PathType != fsrpc.TLFPathType || len(p.TLFComponents) == 0 { 41 // Nothing to do. 42 return nil 43 } 44 45 tlfRoot := fsrpc.Path{ 46 PathType: fsrpc.TLFPathType, 47 TLFType: p.TLFType, 48 TLFName: p.TLFName, 49 } 50 tlfNode, err := tlfRoot.GetDirNode(ctx, config) 51 if err != nil { 52 return err 53 } 54 55 currP := tlfRoot 56 currNode := tlfNode 57 for i := 0; i < len(p.TLFComponents); i++ { 58 dirname := p.TLFComponents[i] 59 currP, err = currP.Join(dirname) 60 if err != nil { 61 return err 62 } 63 64 nextNode, err := createDir(ctx, kbfsOps, currNode, dirname, currP.String(), verbose) 65 if err == (data.NameExistsError{Name: dirname}) { 66 nextNode, _, err = kbfsOps.Lookup( 67 ctx, currNode, currNode.ChildName(dirname)) 68 } 69 if err != nil { 70 return err 71 } 72 currNode = nextNode 73 } 74 } else { 75 if p.PathType != fsrpc.TLFPathType { 76 return data.NameExistsError{Name: p.String()} 77 } 78 79 parentDir, dirname, err := p.DirAndBasename() 80 if err != nil { 81 return err 82 } 83 84 if parentDir.PathType != fsrpc.TLFPathType { 85 // TODO: Ideally, this would error out if 86 // p already existed. 87 _, err := p.GetDirNode(ctx, config) 88 maybePrintPath(p.String(), err, verbose) 89 return err 90 } 91 92 parentNode, err := parentDir.GetDirNode(ctx, config) 93 if err != nil { 94 return err 95 } 96 97 _, err = createDir(ctx, kbfsOps, parentNode, dirname, p.String(), verbose) 98 if err != nil { 99 return err 100 } 101 } 102 103 return nil 104 } 105 106 func mkdir(ctx context.Context, config libkbfs.Config, args []string) (exitStatus int) { 107 flags := flag.NewFlagSet("kbfs mkdir", flag.ContinueOnError) 108 createIntermediate := flags.Bool("p", false, "Create intermediate directories as required.") 109 verbose := flags.Bool("v", false, "Print extra status output.") 110 err := flags.Parse(args) 111 if err != nil { 112 printError("mkdir", err) 113 return 1 114 } 115 116 nodePaths := flags.Args() 117 if len(nodePaths) == 0 { 118 printError("mkdir", errAtLeastOnePath) 119 return 1 120 } 121 122 for _, nodePath := range nodePaths { 123 err := mkdirOne(ctx, config, nodePath, *createIntermediate, *verbose) 124 if err != nil { 125 printError("mkdir", err) 126 exitStatus = 1 127 } 128 } 129 return 130 }