github.com/keybase/client/go@v0.0.0-20240520164431-4f512a4c85a3/client/cmd_simplefs_sync_show.go (about) 1 // Copyright 2018 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package client 5 6 import ( 7 "fmt" 8 "path" 9 "time" 10 11 "github.com/keybase/cli" 12 "github.com/keybase/client/go/libcmdline" 13 "github.com/keybase/client/go/libkb" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 "golang.org/x/net/context" 16 ) 17 18 // CmdSimpleFSSyncShow is the 'fs sync show' command. 19 type CmdSimpleFSSyncShow struct { 20 libkb.Contextified 21 path keybase1.Path 22 getAll bool 23 } 24 25 // NewCmdSimpleFSSyncShow creates a new cli.Command. 26 func NewCmdSimpleFSSyncShow( 27 cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command { 28 return cli.Command{ 29 Name: "show", 30 ArgumentHelp: "<path-to-folder>", 31 Usage: "shows the sync configuration and status for the given folder, or all folders if none is specified", 32 Action: func(c *cli.Context) { 33 cl.ChooseCommand(&CmdSimpleFSSyncShow{ 34 Contextified: libkb.NewContextified(g)}, "show", c) 35 cl.SetNoStandalone() 36 }, 37 } 38 } 39 40 func printBytesStored(ui libkb.TerminalUI, bytes int64, tab string) { 41 if bytes >= 0 { 42 ui.Printf("%s%s bytes stored\n", tab, humanizeBytes(bytes, false)) 43 } 44 } 45 46 func printPrefetchStatus( 47 ui libkb.TerminalUI, status keybase1.FolderSyncStatus, tab string) { 48 switch status.PrefetchStatus { 49 case keybase1.PrefetchStatus_COMPLETE: 50 ui.Printf("%sStatus: fully synced\n", tab) 51 case keybase1.PrefetchStatus_IN_PROGRESS: 52 ui.Printf("%sStatus: sync in progress\n", tab) 53 progress := status.PrefetchProgress 54 if progress.BytesTotal > 0 { 55 ui.Printf("%s%s/%s (%.2f%%)\n", 56 tab, humanizeBytes(progress.BytesFetched, false), 57 humanizeBytes(progress.BytesTotal, false), 58 100*float64(progress.BytesFetched)/ 59 float64(progress.BytesTotal)) 60 } 61 if progress.EndEstimate > 0 && !status.OutOfSyncSpace { 62 timeRemaining := time.Until(keybase1.FromTime(progress.EndEstimate)) 63 ui.Printf("%sEstimated time remaining: %s\n", 64 tab, timeRemaining.Round(1*time.Second)) 65 } else if status.OutOfSyncSpace { 66 ui.Printf("%sError: out of disk space\n", tab) 67 } 68 case keybase1.PrefetchStatus_NOT_STARTED: 69 ui.Printf("%sStatus: sync not yet started\n", tab) 70 default: 71 ui.Printf("%sStatus: unknown\n", tab) 72 } 73 printBytesStored(ui, status.StoredBytesTotal, tab) 74 } 75 76 func appendToTlfPath(tlfPath keybase1.Path, p string) (keybase1.Path, error) { 77 return makeSimpleFSPath( 78 path.Join([]string{mountDir, tlfPath.String(), p}...)) 79 } 80 81 func printLocalStats( 82 ui libkb.TerminalUI, status keybase1.FolderSyncStatus) { 83 a := status.LocalDiskBytesAvailable 84 t := status.LocalDiskBytesTotal 85 ui.Printf("%s (%.2f%%) of the local disk is available for caching.\n", 86 humanizeBytes(a, false), float64(a)/float64(t)*100) 87 } 88 89 func printFolderStatus( 90 ctx context.Context, cli keybase1.SimpleFSClient, ui libkb.TerminalUI, 91 config keybase1.FolderSyncConfig, status keybase1.FolderSyncStatus, 92 tab string, tlfPath keybase1.Path, doPrintLocalStats bool) error { 93 switch config.Mode { 94 case keybase1.FolderSyncMode_DISABLED: 95 ui.Printf("%sSyncing disabled\n", tab) 96 case keybase1.FolderSyncMode_ENABLED: 97 ui.Printf("%sSyncing enabled\n", tab) 98 printPrefetchStatus(ui, status, tab) 99 if doPrintLocalStats { 100 printLocalStats(ui, status) 101 } 102 case keybase1.FolderSyncMode_PARTIAL: 103 // Show all the paths for the TLF, even if a more specific 104 // path was passed in. 105 paths := "these subpaths" 106 if len(config.Paths) == 1 { 107 paths = "this subpath" 108 } 109 ui.Printf("%sSyncing configured for %s:\n", tab, paths) 110 for _, p := range config.Paths { 111 fullPath, err := appendToTlfPath(tlfPath, p) 112 if err != nil { 113 ui.Printf("\tError: %v", err) 114 continue 115 } 116 e, err := cli.SimpleFSStat( 117 ctx, keybase1.SimpleFSStatArg{Path: fullPath}) 118 if err != nil { 119 ui.Printf("\tError: %v", err) 120 continue 121 } 122 123 ui.Printf("%s\t%s\n", tab, p) 124 pathStatus := keybase1.FolderSyncStatus{ 125 PrefetchStatus: e.PrefetchStatus, 126 PrefetchProgress: e.PrefetchProgress, 127 StoredBytesTotal: -1, 128 OutOfSyncSpace: status.OutOfSyncSpace, 129 } 130 printPrefetchStatus(ui, pathStatus, tab+"\t\t") 131 } 132 printBytesStored(ui, status.StoredBytesTotal, tab) 133 if doPrintLocalStats { 134 printLocalStats(ui, status) 135 } 136 default: 137 return fmt.Errorf("Unknown sync mode: %s", config.Mode) 138 } 139 return nil 140 } 141 142 // Run runs the command in client/server mode. 143 func (c *CmdSimpleFSSyncShow) Run() error { 144 cli, err := GetSimpleFSClient(c.G()) 145 if err != nil { 146 return err 147 } 148 149 ctx := context.TODO() 150 ui := c.G().UI.GetTerminalUI() 151 if c.getAll { 152 res, err := cli.SimpleFSSyncConfigAndStatus(ctx, nil) 153 if err != nil { 154 return err 155 } 156 157 for _, folder := range res.Folders { 158 p, err := makeSimpleFSPath(mountDir + "/" + folder.Folder.String()) 159 if err != nil { 160 return err 161 } 162 ui.Printf("%s\n", folder.Folder) 163 err = printFolderStatus( 164 ctx, cli, ui, folder.Config, folder.Status, " ", p, false) 165 if err != nil { 166 return err 167 } 168 ui.Printf("\n") 169 } 170 171 printPrefetchStatus(ui, res.OverallStatus, "") 172 printLocalStats(ui, res.OverallStatus) 173 } else { 174 res, err := cli.SimpleFSFolderSyncConfigAndStatus(ctx, c.path) 175 if err != nil { 176 return err 177 } 178 tlfPath, err := toTlfPath(c.path) 179 if err != nil { 180 return err 181 } 182 return printFolderStatus( 183 ctx, cli, ui, res.Config, res.Status, "", tlfPath, true) 184 } 185 186 return nil 187 } 188 189 // ParseArgv gets the required path. 190 func (c *CmdSimpleFSSyncShow) ParseArgv(ctx *cli.Context) error { 191 if len(ctx.Args()) > 1 { 192 return fmt.Errorf("wrong number of arguments") 193 } 194 195 if len(ctx.Args()) == 1 { 196 p, err := makeSimpleFSPath(ctx.Args()[0]) 197 if err != nil { 198 return err 199 } 200 c.path = p 201 } else { 202 c.getAll = true 203 } 204 return nil 205 } 206 207 // GetUsage says what this command needs to operate. 208 func (c *CmdSimpleFSSyncShow) GetUsage() libkb.Usage { 209 return libkb.Usage{ 210 Config: true, 211 KbKeyring: true, 212 API: true, 213 } 214 }