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  }