github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/service/simplefs.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package service
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/keybase/client/go/libkb"
    10  	"github.com/keybase/client/go/protocol/keybase1"
    11  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    12  	"github.com/pkg/errors"
    13  	"golang.org/x/net/context"
    14  )
    15  
    16  // Fast operations like Stat usually finish fairly quickly. Slow
    17  // operations in SimpleFS are handled in an async manner, where the RPC starts
    18  // the operation but does not wait for it to finish (there's SimpleFSWait). So
    19  // it probably seems like this is too long a timeout since all RPCs except for
    20  // SimpleFSWait should return fairly fast. However, when user first navigates
    21  // into a TLF, it might still take much longer, especially on a slow network.
    22  // So just cap it at 1 minute.
    23  const simpleFSTimeout = 1 * time.Minute
    24  
    25  type SimpleFSHandler struct {
    26  	*BaseHandler
    27  	libkb.Contextified
    28  }
    29  
    30  func NewSimpleFSHandler(xp rpc.Transporter, g *libkb.GlobalContext) *SimpleFSHandler {
    31  	return &SimpleFSHandler{
    32  		BaseHandler:  NewBaseHandler(g, xp),
    33  		Contextified: libkb.NewContextified(g),
    34  	}
    35  }
    36  
    37  var _ keybase1.SimpleFSInterface = (*SimpleFSHandler)(nil)
    38  
    39  func (s *SimpleFSHandler) wrapContextWithTimeout(ctx context.Context) (newCtx context.Context, cancel func()) {
    40  	return context.WithTimeout(ctx, simpleFSTimeout)
    41  }
    42  
    43  const waitForTransporterInterval = time.Second / 4
    44  const waitForTransporterTimeout = time.Minute
    45  
    46  type WaitingForKBFSTimeoutError struct {
    47  	originalError error
    48  }
    49  
    50  // Error implements the error interface.
    51  func (e WaitingForKBFSTimeoutError) Error() string {
    52  	return errors.WithMessage(e.originalError, "timeout waiting for kbfs").Error()
    53  }
    54  
    55  // Cause makes it work with errors.Cause().
    56  func (e WaitingForKBFSTimeoutError) Cause() error {
    57  	return e.originalError
    58  }
    59  
    60  // HumanError implements the HumanErrorer interface used in libkb/errors.
    61  // Without this, the Cause will end up being returned to GUI.
    62  func (e WaitingForKBFSTimeoutError) HumanError() error {
    63  	return e
    64  }
    65  
    66  // ToStatus implements the ExportableError interface.
    67  func (e WaitingForKBFSTimeoutError) ToStatus() keybase1.Status {
    68  	return keybase1.Status{
    69  		Code: int(keybase1.StatusCode_SCKBFSClientTimeout),
    70  		Name: "SC_KBFS_CLIENT_TIMEOUT",
    71  		Desc: "timeout waiting for kbfs",
    72  	}
    73  }
    74  
    75  func (s *SimpleFSHandler) client(ctx context.Context) (*keybase1.SimpleFSClient, error) {
    76  	ctx, cancel := context.WithTimeout(ctx, waitForTransporterTimeout)
    77  	defer cancel()
    78  	xp := s.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
    79  	for xp == nil {
    80  		select {
    81  		case <-ctx.Done():
    82  			return nil, WaitingForKBFSTimeoutError{ctx.Err()}
    83  		default:
    84  		}
    85  		time.Sleep(waitForTransporterInterval)
    86  		xp = s.G().ConnectionManager.LookupByClientType(keybase1.ClientType_KBFS)
    87  	}
    88  	return &keybase1.SimpleFSClient{
    89  		Cli: rpc.NewClient(xp, libkb.NewContextifiedErrorUnwrapper(s.G()), nil),
    90  	}, nil
    91  }
    92  
    93  // SimpleFSList - Begin list of items in directory at path
    94  // Retrieve results with readList()
    95  // Can be a single file to get flags/status
    96  func (s *SimpleFSHandler) SimpleFSList(ctx context.Context, arg keybase1.SimpleFSListArg) error {
    97  	cli, err := s.client(ctx)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   102  	defer cancel()
   103  	return cli.SimpleFSList(ctx, arg)
   104  }
   105  
   106  // SimpleFSListRecursive - Begin recursive list of items in directory at path
   107  func (s *SimpleFSHandler) SimpleFSListRecursive(ctx context.Context, arg keybase1.SimpleFSListRecursiveArg) error {
   108  	cli, err := s.client(ctx)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   113  	defer cancel()
   114  	return cli.SimpleFSListRecursive(ctx, arg)
   115  }
   116  
   117  // SimpleFSFolderSetSyncConfig implements the SimpleFSInterface.
   118  func (s *SimpleFSHandler) SimpleFSListFavorites(ctx context.Context) (
   119  	keybase1.FavoritesResult, error) {
   120  	cli, err := s.client(ctx)
   121  	if err != nil {
   122  		return keybase1.FavoritesResult{}, err
   123  	}
   124  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   125  	defer cancel()
   126  	return cli.SimpleFSListFavorites(ctx)
   127  }
   128  
   129  // SimpleFSListRecursiveToDepth - Begin recursive list of items in directory at
   130  // path to a given depth.
   131  func (s *SimpleFSHandler) SimpleFSListRecursiveToDepth(ctx context.Context, arg keybase1.SimpleFSListRecursiveToDepthArg) error {
   132  	cli, err := s.client(ctx)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   137  	defer cancel()
   138  	return cli.SimpleFSListRecursiveToDepth(ctx, arg)
   139  }
   140  
   141  // SimpleFSReadList - Get list of Paths in progress. Can indicate status of pending
   142  // to get more entries.
   143  func (s *SimpleFSHandler) SimpleFSReadList(ctx context.Context, arg keybase1.OpID) (keybase1.SimpleFSListResult, error) {
   144  	cli, err := s.client(ctx)
   145  	if err != nil {
   146  		return keybase1.SimpleFSListResult{}, err
   147  	}
   148  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   149  	defer cancel()
   150  	return cli.SimpleFSReadList(ctx, arg)
   151  }
   152  
   153  // SimpleFSCopy - Begin copy of file or directory
   154  func (s *SimpleFSHandler) SimpleFSCopy(ctx context.Context, arg keybase1.SimpleFSCopyArg) error {
   155  	cli, err := s.client(ctx)
   156  	if err != nil {
   157  		return err
   158  	}
   159  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   160  	defer cancel()
   161  	return cli.SimpleFSCopy(ctx, arg)
   162  }
   163  
   164  // SimpleFSCopyRecursive - Begin recursive copy of directory
   165  func (s *SimpleFSHandler) SimpleFSCopyRecursive(ctx context.Context, arg keybase1.SimpleFSCopyRecursiveArg) error {
   166  	cli, err := s.client(ctx)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   171  	defer cancel()
   172  	return cli.SimpleFSCopyRecursive(ctx, arg)
   173  }
   174  
   175  // SimpleFSMove - Begin move of file or directory, from/to KBFS only
   176  func (s *SimpleFSHandler) SimpleFSMove(ctx context.Context, arg keybase1.SimpleFSMoveArg) error {
   177  	cli, err := s.client(ctx)
   178  	if err != nil {
   179  		return err
   180  	}
   181  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   182  	defer cancel()
   183  	return cli.SimpleFSMove(ctx, arg)
   184  }
   185  
   186  // SimpleFSRename - Rename file or directory, KBFS side only
   187  func (s *SimpleFSHandler) SimpleFSRename(ctx context.Context, arg keybase1.SimpleFSRenameArg) error {
   188  	cli, err := s.client(ctx)
   189  	if err != nil {
   190  		return err
   191  	}
   192  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   193  	defer cancel()
   194  	return cli.SimpleFSRename(ctx, arg)
   195  }
   196  
   197  // SimpleFSSymlink - Make a symlink from KBFS to either elsewhere in KBFS or in the regular filesystem
   198  func (s *SimpleFSHandler) SimpleFSSymlink(ctx context.Context, arg keybase1.SimpleFSSymlinkArg) error {
   199  	cli, err := s.client(ctx)
   200  	if err != nil {
   201  		return err
   202  	}
   203  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   204  	defer cancel()
   205  	return cli.SimpleFSSymlink(ctx, arg)
   206  }
   207  
   208  // SimpleFSOpen - Create/open a file and leave it open
   209  // or create a directory
   210  // Files must be closed afterwards.
   211  func (s *SimpleFSHandler) SimpleFSOpen(ctx context.Context, arg keybase1.SimpleFSOpenArg) error {
   212  	cli, err := s.client(ctx)
   213  	if err != nil {
   214  		return err
   215  	}
   216  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   217  	defer cancel()
   218  	return cli.SimpleFSOpen(ctx, arg)
   219  }
   220  
   221  // SimpleFSSetStat - Set/clear file bits - only executable for now
   222  func (s *SimpleFSHandler) SimpleFSSetStat(ctx context.Context, arg keybase1.SimpleFSSetStatArg) error {
   223  	cli, err := s.client(ctx)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   228  	defer cancel()
   229  	return cli.SimpleFSSetStat(ctx, arg)
   230  }
   231  
   232  // SimpleFSRead - Read (possibly partial) contents of open file,
   233  // up to the amount specified by size.
   234  // Repeat until zero bytes are returned or error.
   235  // If size is zero, read an arbitrary amount.
   236  func (s *SimpleFSHandler) SimpleFSRead(ctx context.Context, arg keybase1.SimpleFSReadArg) (keybase1.FileContent, error) {
   237  	cli, err := s.client(ctx)
   238  	if err != nil {
   239  		return keybase1.FileContent{}, err
   240  	}
   241  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   242  	defer cancel()
   243  	return cli.SimpleFSRead(ctx, arg)
   244  }
   245  
   246  // SimpleFSWrite - Append content to opened file.
   247  // May be repeated until OpID is closed.
   248  func (s *SimpleFSHandler) SimpleFSWrite(ctx context.Context, arg keybase1.SimpleFSWriteArg) error {
   249  	cli, err := s.client(ctx)
   250  	if err != nil {
   251  		return err
   252  	}
   253  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   254  	defer cancel()
   255  	return cli.SimpleFSWrite(ctx, arg)
   256  }
   257  
   258  // SimpleFSRemove - Remove file or directory from filesystem
   259  func (s *SimpleFSHandler) SimpleFSRemove(ctx context.Context, arg keybase1.SimpleFSRemoveArg) error {
   260  	cli, err := s.client(ctx)
   261  	if err != nil {
   262  		return err
   263  	}
   264  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   265  	defer cancel()
   266  	return cli.SimpleFSRemove(ctx, arg)
   267  }
   268  
   269  // SimpleFSStat - Get info about file
   270  func (s *SimpleFSHandler) SimpleFSStat(ctx context.Context, arg keybase1.SimpleFSStatArg) (keybase1.Dirent, error) {
   271  	cli, err := s.client(ctx)
   272  	if err != nil {
   273  		return keybase1.Dirent{}, err
   274  	}
   275  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   276  	defer cancel()
   277  	return cli.SimpleFSStat(ctx, arg)
   278  }
   279  
   280  // SimpleFSGetRevisions - Get revision info for a directory entry
   281  func (s *SimpleFSHandler) SimpleFSGetRevisions(
   282  	ctx context.Context, arg keybase1.SimpleFSGetRevisionsArg) error {
   283  	cli, err := s.client(ctx)
   284  	if err != nil {
   285  		return err
   286  	}
   287  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   288  	defer cancel()
   289  	return cli.SimpleFSGetRevisions(ctx, arg)
   290  }
   291  
   292  // SimpleFSReadRevisions - Get list of revisions in progress. Can
   293  // indicate status of pending to get more entries.
   294  func (s *SimpleFSHandler) SimpleFSReadRevisions(
   295  	ctx context.Context, opID keybase1.OpID) (
   296  	keybase1.GetRevisionsResult, error) {
   297  	cli, err := s.client(ctx)
   298  	if err != nil {
   299  		return keybase1.GetRevisionsResult{}, err
   300  	}
   301  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   302  	defer cancel()
   303  	return cli.SimpleFSReadRevisions(ctx, opID)
   304  }
   305  
   306  // SimpleFSMakeOpid - Convenience helper for generating new random value
   307  func (s *SimpleFSHandler) SimpleFSMakeOpid(ctx context.Context) (keybase1.OpID, error) {
   308  	cli, err := s.client(ctx)
   309  	if err != nil {
   310  		return keybase1.OpID{}, err
   311  	}
   312  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   313  	defer cancel()
   314  	return cli.SimpleFSMakeOpid(ctx)
   315  }
   316  
   317  // SimpleFSClose - Close OpID, cancels any pending operation.
   318  // Must be called after list/copy/remove
   319  func (s *SimpleFSHandler) SimpleFSClose(ctx context.Context, arg keybase1.OpID) error {
   320  	cli, err := s.client(ctx)
   321  	if err != nil {
   322  		return err
   323  	}
   324  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   325  	defer cancel()
   326  	return cli.SimpleFSClose(ctx, arg)
   327  }
   328  
   329  // SimpleFSCancel - Cancels a running operation, like copy.
   330  func (s *SimpleFSHandler) SimpleFSCancel(ctx context.Context, arg keybase1.OpID) error {
   331  	cli, err := s.client(ctx)
   332  	if err != nil {
   333  		return err
   334  	}
   335  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   336  	defer cancel()
   337  	return cli.SimpleFSCancel(ctx, arg)
   338  }
   339  
   340  // SimpleFSCheck - Check progress of pending operation
   341  func (s *SimpleFSHandler) SimpleFSCheck(ctx context.Context, arg keybase1.OpID) (keybase1.OpProgress, error) {
   342  	cli, err := s.client(ctx)
   343  	if err != nil {
   344  		return keybase1.OpProgress{}, err
   345  	}
   346  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   347  	defer cancel()
   348  	return cli.SimpleFSCheck(ctx, arg)
   349  }
   350  
   351  // SimpleFSGetOps - Get all the outstanding operations
   352  func (s *SimpleFSHandler) SimpleFSGetOps(ctx context.Context) ([]keybase1.OpDescription, error) {
   353  	cli, err := s.client(ctx)
   354  	if err != nil {
   355  		return nil, err
   356  	}
   357  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   358  	defer cancel()
   359  	return cli.SimpleFSGetOps(ctx)
   360  }
   361  
   362  // SimpleFSWait - Blocking wait for the pending operation to finish
   363  func (s *SimpleFSHandler) SimpleFSWait(ctx context.Context, arg keybase1.OpID) error {
   364  	cli, err := s.client(ctx)
   365  	if err != nil {
   366  		return err
   367  	}
   368  	return cli.SimpleFSWait(ctx, arg)
   369  }
   370  
   371  // SimpleFSDumpDebuggingInfo - Instructs KBFS to dump debugging info
   372  // into its logs.
   373  func (s *SimpleFSHandler) SimpleFSDumpDebuggingInfo(ctx context.Context) error {
   374  	cli, err := s.client(ctx)
   375  	if err != nil {
   376  		return err
   377  	}
   378  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   379  	defer cancel()
   380  	return cli.SimpleFSDumpDebuggingInfo(ctx)
   381  }
   382  
   383  // SimpleFSSyncStatus - Get sync status.
   384  func (s *SimpleFSHandler) SimpleFSSyncStatus(ctx context.Context, filter keybase1.ListFilter) (keybase1.FSSyncStatus, error) {
   385  	cli, err := s.client(ctx)
   386  	if err != nil {
   387  		return keybase1.FSSyncStatus{}, err
   388  	}
   389  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   390  	defer cancel()
   391  	return cli.SimpleFSSyncStatus(ctx, filter)
   392  }
   393  
   394  // SimpleFSUserEditHistory implements the SimpleFSInterface.
   395  func (s *SimpleFSHandler) SimpleFSUserEditHistory(ctx context.Context) (
   396  	res []keybase1.FSFolderEditHistory, err error) {
   397  	cli, err := s.client(ctx)
   398  	if err != nil {
   399  		return nil, err
   400  	}
   401  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   402  	defer cancel()
   403  	return cli.SimpleFSUserEditHistory(ctx)
   404  }
   405  
   406  // SimpleFSFolderEditHistory implements the SimpleFSInterface.
   407  func (s *SimpleFSHandler) SimpleFSFolderEditHistory(
   408  	ctx context.Context, path keybase1.Path) (
   409  	res keybase1.FSFolderEditHistory, err error) {
   410  	cli, err := s.client(ctx)
   411  	if err != nil {
   412  		return keybase1.FSFolderEditHistory{}, err
   413  	}
   414  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   415  	defer cancel()
   416  	return cli.SimpleFSFolderEditHistory(ctx, path)
   417  }
   418  
   419  // SimpleFSReset implements the SimpleFSInterface.
   420  func (s *SimpleFSHandler) SimpleFSReset(
   421  	ctx context.Context, arg keybase1.SimpleFSResetArg) (err error) {
   422  	cli, err := s.client(ctx)
   423  	if err != nil {
   424  		return err
   425  	}
   426  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   427  	defer cancel()
   428  	return cli.SimpleFSReset(ctx, arg)
   429  }
   430  
   431  // SimpleFSGetUserQuotaUsage implements the SimpleFSInterface.
   432  func (s *SimpleFSHandler) SimpleFSGetUserQuotaUsage(ctx context.Context) (
   433  	keybase1.SimpleFSQuotaUsage, error) {
   434  	cli, err := s.client(ctx)
   435  	if err != nil {
   436  		return keybase1.SimpleFSQuotaUsage{}, err
   437  	}
   438  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   439  	defer cancel()
   440  	return cli.SimpleFSGetUserQuotaUsage(ctx)
   441  }
   442  
   443  // SimpleFSGetTeamQuotaUsage implements the SimpleFSInterface.
   444  func (s *SimpleFSHandler) SimpleFSGetTeamQuotaUsage(
   445  	ctx context.Context, teamName keybase1.TeamName) (
   446  	keybase1.SimpleFSQuotaUsage, error) {
   447  	cli, err := s.client(ctx)
   448  	if err != nil {
   449  		return keybase1.SimpleFSQuotaUsage{}, err
   450  	}
   451  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   452  	defer cancel()
   453  	return cli.SimpleFSGetTeamQuotaUsage(ctx, teamName)
   454  }
   455  
   456  // SimpleFSGetFolder implements the SimpleFSInterface.
   457  func (s *SimpleFSHandler) SimpleFSGetFolder(
   458  	ctx context.Context, kbfsPath keybase1.KBFSPath) (
   459  	res keybase1.FolderWithFavFlags, err error) {
   460  	cli, err := s.client(ctx)
   461  	if err != nil {
   462  		return keybase1.FolderWithFavFlags{}, err
   463  	}
   464  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   465  	defer cancel()
   466  	return cli.SimpleFSGetFolder(ctx, kbfsPath)
   467  }
   468  
   469  // SimpleFSFolderSyncConfigAndStatus implements the SimpleFSInterface.
   470  func (s *SimpleFSHandler) SimpleFSFolderSyncConfigAndStatus(
   471  	ctx context.Context, path keybase1.Path) (
   472  	keybase1.FolderSyncConfigAndStatus, error) {
   473  	cli, err := s.client(ctx)
   474  	if err != nil {
   475  		return keybase1.FolderSyncConfigAndStatus{}, err
   476  	}
   477  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   478  	defer cancel()
   479  	return cli.SimpleFSFolderSyncConfigAndStatus(ctx, path)
   480  }
   481  
   482  // SimpleFSFolderSetSyncConfig implements the SimpleFSInterface.
   483  func (s *SimpleFSHandler) SimpleFSSetFolderSyncConfig(
   484  	ctx context.Context, arg keybase1.SimpleFSSetFolderSyncConfigArg) error {
   485  	cli, err := s.client(ctx)
   486  	if err != nil {
   487  		return err
   488  	}
   489  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   490  	defer cancel()
   491  	return cli.SimpleFSSetFolderSyncConfig(ctx, arg)
   492  }
   493  
   494  // SimpleFSSyncConfigAndStatus implements the SimpleFSInterface.
   495  func (s *SimpleFSHandler) SimpleFSSyncConfigAndStatus(
   496  	ctx context.Context, identifyBehavior *keybase1.TLFIdentifyBehavior) (keybase1.SyncConfigAndStatusRes, error) {
   497  	cli, err := s.client(ctx)
   498  	if err != nil {
   499  		return keybase1.SyncConfigAndStatusRes{}, err
   500  	}
   501  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   502  	defer cancel()
   503  	return cli.SimpleFSSyncConfigAndStatus(ctx, identifyBehavior)
   504  }
   505  
   506  // SimpleFSClearConflictState implements the SimpleFSInterface.
   507  func (s *SimpleFSHandler) SimpleFSClearConflictState(ctx context.Context,
   508  	path keybase1.Path) error {
   509  	cli, err := s.client(ctx)
   510  	if err != nil {
   511  		return err
   512  	}
   513  	// No timeouts since this can be a long operation if the folder is
   514  	// large or the disk is slow, and this is a synchronous operation.
   515  	return cli.SimpleFSClearConflictState(ctx, path)
   516  }
   517  
   518  // SimpleFSFinishResolvingConflict implements the SimpleFSInterface.
   519  func (s *SimpleFSHandler) SimpleFSFinishResolvingConflict(ctx context.Context,
   520  	path keybase1.Path) error {
   521  	cli, err := s.client(ctx)
   522  	if err != nil {
   523  		return err
   524  	}
   525  	// No timeouts since this can be a long operation if the folder is
   526  	// large or the disk is slow, and this is a synchronous operation.
   527  	return cli.SimpleFSFinishResolvingConflict(ctx, path)
   528  }
   529  
   530  // SimpleFSForceStuckConflict implements the SimpleFSInterface.
   531  func (s *SimpleFSHandler) SimpleFSForceStuckConflict(
   532  	ctx context.Context, path keybase1.Path) error {
   533  	cli, err := s.client(ctx)
   534  	if err != nil {
   535  		return err
   536  	}
   537  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   538  	defer cancel()
   539  	return cli.SimpleFSForceStuckConflict(ctx, path)
   540  }
   541  
   542  // SimpleFSGetOnlineStatus implements the SimpleFSInterface.
   543  func (s *SimpleFSHandler) SimpleFSGetOnlineStatus(
   544  	ctx context.Context, clientID string) (keybase1.KbfsOnlineStatus, error) {
   545  	cli, err := s.client(ctx)
   546  	if err != nil {
   547  		return keybase1.KbfsOnlineStatus_OFFLINE, err
   548  	}
   549  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   550  	defer cancel()
   551  	return cli.SimpleFSGetOnlineStatus(ctx, clientID)
   552  }
   553  
   554  // SimpleFSCheckReachability implements the SimpleFSInterface.
   555  func (s *SimpleFSHandler) SimpleFSCheckReachability(ctx context.Context) error {
   556  	cli, err := s.client(ctx)
   557  	if err != nil {
   558  		return err
   559  	}
   560  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   561  	defer cancel()
   562  	return cli.SimpleFSCheckReachability(ctx)
   563  }
   564  
   565  // SimpleFSSetDebugLevel implements the SimpleFSInterface.
   566  func (s *SimpleFSHandler) SimpleFSSetDebugLevel(
   567  	ctx context.Context, level string) error {
   568  	cli, err := s.client(ctx)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   573  	defer cancel()
   574  	return cli.SimpleFSSetDebugLevel(ctx, level)
   575  }
   576  
   577  // SimpleFSSettings implements the SimpleFSInterface.
   578  func (s *SimpleFSHandler) SimpleFSSettings(
   579  	ctx context.Context) (keybase1.FSSettings, error) {
   580  	cli, err := s.client(ctx)
   581  	if err != nil {
   582  		return keybase1.FSSettings{}, err
   583  	}
   584  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   585  	defer cancel()
   586  	return cli.SimpleFSSettings(ctx)
   587  }
   588  
   589  // SimpleFSSetNotificationThreshold implements the SimpleFSInterface.
   590  func (s *SimpleFSHandler) SimpleFSSetNotificationThreshold(
   591  	ctx context.Context, threshold int64) error {
   592  	cli, err := s.client(ctx)
   593  	if err != nil {
   594  		return err
   595  	}
   596  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   597  	defer cancel()
   598  	return cli.SimpleFSSetNotificationThreshold(ctx, threshold)
   599  }
   600  
   601  // SimpleFSObfuscatePath implements the SimpleFSInterface.
   602  func (s *SimpleFSHandler) SimpleFSObfuscatePath(
   603  	ctx context.Context, path keybase1.Path) (res string, err error) {
   604  	cli, err := s.client(ctx)
   605  	if err != nil {
   606  		return "", err
   607  	}
   608  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   609  	defer cancel()
   610  	return cli.SimpleFSObfuscatePath(ctx, path)
   611  }
   612  
   613  // SimpleFSDeobfuscatePath implements the SimpleFSInterface.
   614  func (s *SimpleFSHandler) SimpleFSDeobfuscatePath(
   615  	ctx context.Context, path keybase1.Path) (res []string, err error) {
   616  	cli, err := s.client(ctx)
   617  	if err != nil {
   618  		return nil, err
   619  	}
   620  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   621  	defer cancel()
   622  	return cli.SimpleFSDeobfuscatePath(ctx, path)
   623  }
   624  
   625  // SimpleFSGetStats implements the SimpleFSInterface.
   626  func (s *SimpleFSHandler) SimpleFSGetStats(ctx context.Context) (
   627  	keybase1.SimpleFSStats, error) {
   628  	cli, err := s.client(ctx)
   629  	if err != nil {
   630  		return keybase1.SimpleFSStats{}, err
   631  	}
   632  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   633  	defer cancel()
   634  	return cli.SimpleFSGetStats(ctx)
   635  }
   636  
   637  func (s *SimpleFSHandler) SimpleFSSubscribeNonPath(ctx context.Context, arg keybase1.SimpleFSSubscribeNonPathArg) error {
   638  	cli, err := s.client(ctx)
   639  	if err != nil {
   640  		return err
   641  	}
   642  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   643  	defer cancel()
   644  	return cli.SimpleFSSubscribeNonPath(ctx, arg)
   645  }
   646  
   647  func (s *SimpleFSHandler) SimpleFSSubscribePath(ctx context.Context, arg keybase1.SimpleFSSubscribePathArg) error {
   648  	cli, err := s.client(ctx)
   649  	if err != nil {
   650  		return err
   651  	}
   652  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   653  	defer cancel()
   654  	return cli.SimpleFSSubscribePath(ctx, arg)
   655  }
   656  
   657  func (s *SimpleFSHandler) SimpleFSUnsubscribe(ctx context.Context, arg keybase1.SimpleFSUnsubscribeArg) error {
   658  	cli, err := s.client(ctx)
   659  	if err != nil {
   660  		return err
   661  	}
   662  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   663  	defer cancel()
   664  	return cli.SimpleFSUnsubscribe(ctx, arg)
   665  }
   666  
   667  func (s *SimpleFSHandler) SimpleFSStartDownload(
   668  	ctx context.Context, arg keybase1.SimpleFSStartDownloadArg) (downloadID string, err error) {
   669  	cli, err := s.client(ctx)
   670  	if err != nil {
   671  		return "", err
   672  	}
   673  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   674  	defer cancel()
   675  	return cli.SimpleFSStartDownload(ctx, arg)
   676  }
   677  
   678  func (s *SimpleFSHandler) SimpleFSGetDownloadStatus(ctx context.Context) (
   679  	status keybase1.DownloadStatus, err error) {
   680  	cli, err := s.client(ctx)
   681  	if err != nil {
   682  		return keybase1.DownloadStatus{}, err
   683  	}
   684  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   685  	defer cancel()
   686  	return cli.SimpleFSGetDownloadStatus(ctx)
   687  }
   688  
   689  func (s *SimpleFSHandler) SimpleFSCancelDownload(
   690  	ctx context.Context, downloadID string) (err error) {
   691  	cli, err := s.client(ctx)
   692  	if err != nil {
   693  		return err
   694  	}
   695  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   696  	defer cancel()
   697  	return cli.SimpleFSCancelDownload(ctx, downloadID)
   698  }
   699  
   700  func (s *SimpleFSHandler) SimpleFSDismissDownload(
   701  	ctx context.Context, downloadID string) (err error) {
   702  	cli, err := s.client(ctx)
   703  	if err != nil {
   704  		return err
   705  	}
   706  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   707  	defer cancel()
   708  	return cli.SimpleFSDismissDownload(ctx, downloadID)
   709  }
   710  
   711  func (s *SimpleFSHandler) SimpleFSGetDownloadInfo(
   712  	ctx context.Context, downloadID string) (downloadInfo keybase1.DownloadInfo, err error) {
   713  	cli, err := s.client(ctx)
   714  	if err != nil {
   715  		return keybase1.DownloadInfo{}, err
   716  	}
   717  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   718  	defer cancel()
   719  	return cli.SimpleFSGetDownloadInfo(ctx, downloadID)
   720  }
   721  
   722  func (s *SimpleFSHandler) SimpleFSConfigureDownload(
   723  	ctx context.Context, arg keybase1.SimpleFSConfigureDownloadArg) (err error) {
   724  	cli, err := s.client(ctx)
   725  	if err != nil {
   726  		return err
   727  	}
   728  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   729  	defer cancel()
   730  	return cli.SimpleFSConfigureDownload(ctx, arg)
   731  }
   732  
   733  // SimpleFSGetGUIFileContext implements the SimpleFSInterface.
   734  func (s *SimpleFSHandler) SimpleFSGetGUIFileContext(ctx context.Context,
   735  	path keybase1.KBFSPath) (resource keybase1.GUIFileContext, err error) {
   736  	cli, err := s.client(ctx)
   737  	if err != nil {
   738  		return keybase1.GUIFileContext{}, err
   739  	}
   740  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   741  	defer cancel()
   742  	return cli.SimpleFSGetGUIFileContext(ctx, path)
   743  }
   744  
   745  // SimpleFSGetFilesTabBadge implements the SimpleFSInterface.
   746  func (s *SimpleFSHandler) SimpleFSGetFilesTabBadge(ctx context.Context) (
   747  	keybase1.FilesTabBadge, error) {
   748  	cli, err := s.client(ctx)
   749  	if err != nil {
   750  		return keybase1.FilesTabBadge_NONE, err
   751  	}
   752  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   753  	defer cancel()
   754  	return cli.SimpleFSGetFilesTabBadge(ctx)
   755  }
   756  
   757  // SimpleFSUserIn implements the SimpleFSInterface.
   758  func (s *SimpleFSHandler) SimpleFSUserIn(ctx context.Context, clientKey string) error {
   759  	cli, err := s.client(ctx)
   760  	if err != nil {
   761  		return err
   762  	}
   763  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   764  	defer cancel()
   765  	return cli.SimpleFSUserIn(ctx, clientKey)
   766  }
   767  
   768  // SimpleFSUserOut implements the SimpleFSInterface.
   769  func (s *SimpleFSHandler) SimpleFSUserOut(ctx context.Context, clientKey string) error {
   770  	cli, err := s.client(ctx)
   771  	if err != nil {
   772  		return err
   773  	}
   774  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   775  	defer cancel()
   776  	return cli.SimpleFSUserOut(ctx, clientKey)
   777  }
   778  
   779  // SimpleFSSetSfmiBannerDismissed implements the SimpleFSInterface.
   780  func (s *SimpleFSHandler) SimpleFSSetSfmiBannerDismissed(ctx context.Context, dismissed bool) error {
   781  	cli, err := s.client(ctx)
   782  	if err != nil {
   783  		return err
   784  	}
   785  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   786  	defer cancel()
   787  	return cli.SimpleFSSetSfmiBannerDismissed(ctx, dismissed)
   788  }
   789  
   790  // SimpleFSSetSfmiBannerDismissed implements the SimpleFSInterface.
   791  func (s *SimpleFSHandler) SimpleFSSetSyncOnCellular(
   792  	ctx context.Context, syncOnCellular bool) error {
   793  	cli, err := s.client(ctx)
   794  	if err != nil {
   795  		return err
   796  	}
   797  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   798  	defer cancel()
   799  	return cli.SimpleFSSetSyncOnCellular(ctx, syncOnCellular)
   800  }
   801  
   802  // SimpleFSSearch implements the SimpleFSInterface.
   803  func (s *SimpleFSHandler) SimpleFSSearch(
   804  	ctx context.Context, arg keybase1.SimpleFSSearchArg) (
   805  	keybase1.SimpleFSSearchResults, error) {
   806  	cli, err := s.client(ctx)
   807  	if err != nil {
   808  		return keybase1.SimpleFSSearchResults{}, err
   809  	}
   810  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   811  	defer cancel()
   812  	return cli.SimpleFSSearch(ctx, arg)
   813  }
   814  
   815  // SimpleFSResetIndex implements the SimpleFSInterface.
   816  func (s *SimpleFSHandler) SimpleFSResetIndex(ctx context.Context) error {
   817  	cli, err := s.client(ctx)
   818  	if err != nil {
   819  		return err
   820  	}
   821  	// Don't use a timeout for resetting the index; let it completely
   822  	// clean up the storage as needed.
   823  	return cli.SimpleFSResetIndex(ctx)
   824  }
   825  
   826  // SimpleFSGetIndexProgress implements the SimpleFSInterface.
   827  func (s *SimpleFSHandler) SimpleFSGetIndexProgress(
   828  	ctx context.Context) (res keybase1.SimpleFSIndexProgress, err error) {
   829  	cli, err := s.client(ctx)
   830  	if err != nil {
   831  		return keybase1.SimpleFSIndexProgress{}, err
   832  	}
   833  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   834  	defer cancel()
   835  	return cli.SimpleFSGetIndexProgress(ctx)
   836  }
   837  
   838  // SimpleFSStartUpload implements the SimpleFSInterface.
   839  func (s *SimpleFSHandler) SimpleFSStartUpload(ctx context.Context,
   840  	arg keybase1.SimpleFSStartUploadArg) (uploadID string, err error) {
   841  	cli, err := s.client(ctx)
   842  	if err != nil {
   843  		return "", err
   844  	}
   845  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   846  	defer cancel()
   847  	return cli.SimpleFSStartUpload(ctx, arg)
   848  }
   849  
   850  // SimpleFSMakeTempDirForUpload implements the SimpleFSInterface.
   851  func (s *SimpleFSHandler) SimpleFSMakeTempDirForUpload(
   852  	ctx context.Context) (dirPath string, err error) {
   853  	cli, err := s.client(ctx)
   854  	if err != nil {
   855  		return "", err
   856  	}
   857  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   858  	defer cancel()
   859  	return cli.SimpleFSMakeTempDirForUpload(ctx)
   860  }
   861  
   862  // SimpleFSGetUploadStatus implements the SimpleFSInterface.
   863  func (s *SimpleFSHandler) SimpleFSGetUploadStatus(
   864  	ctx context.Context) (status []keybase1.UploadState, err error) {
   865  	cli, err := s.client(ctx)
   866  	if err != nil {
   867  		return nil, err
   868  	}
   869  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   870  	defer cancel()
   871  	return cli.SimpleFSGetUploadStatus(ctx)
   872  }
   873  
   874  // SimpleFSCancelUpload implements the SimpleFSInterface.
   875  func (s *SimpleFSHandler) SimpleFSCancelUpload(
   876  	ctx context.Context, uploadID string) (err error) {
   877  	cli, err := s.client(ctx)
   878  	if err != nil {
   879  		return err
   880  	}
   881  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   882  	defer cancel()
   883  	return cli.SimpleFSCancelUpload(ctx, uploadID)
   884  }
   885  
   886  // SimpleFSDismissUpload implements the SimpleFSInterface.
   887  func (s *SimpleFSHandler) SimpleFSDismissUpload(
   888  	ctx context.Context, uploadID string) (err error) {
   889  	cli, err := s.client(ctx)
   890  	if err != nil {
   891  		return err
   892  	}
   893  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   894  	defer cancel()
   895  	return cli.SimpleFSDismissUpload(ctx, uploadID)
   896  }
   897  
   898  // SimpleFSDismissUpload implements the SimpleFSInterface.
   899  func (s *SimpleFSHandler) SimpleFSCancelJournalUploads(
   900  	ctx context.Context, path keybase1.KBFSPath) (err error) {
   901  	cli, err := s.client(ctx)
   902  	if err != nil {
   903  		return err
   904  	}
   905  	// No timeouts since this can be a long operation if the folder is
   906  	// large or the disk is slow, and this is a synchronous operation.
   907  	return cli.SimpleFSCancelJournalUploads(ctx, path)
   908  }
   909  
   910  // SimpleFSArchiveStart implements the SimpleFSInterface.
   911  func (s *SimpleFSHandler) SimpleFSArchiveStart(ctx context.Context,
   912  	arg keybase1.SimpleFSArchiveStartArg) (jobDesc keybase1.SimpleFSArchiveJobDesc, err error) {
   913  	cli, err := s.client(ctx)
   914  	if err != nil {
   915  		return keybase1.SimpleFSArchiveJobDesc{}, err
   916  	}
   917  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   918  	defer cancel()
   919  	return cli.SimpleFSArchiveStart(ctx, arg)
   920  }
   921  
   922  // SimpleFSArchiveCancelOrDismissJob implements the SimpleFSInterface.
   923  func (s *SimpleFSHandler) SimpleFSArchiveCancelOrDismissJob(ctx context.Context,
   924  	jobID string) (err error) {
   925  	cli, err := s.client(ctx)
   926  	if err != nil {
   927  		return err
   928  	}
   929  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   930  	defer cancel()
   931  	return cli.SimpleFSArchiveCancelOrDismissJob(ctx, jobID)
   932  }
   933  
   934  // SimpleFSGetArchiveStatus implements the SimpleFSInterface.
   935  func (s *SimpleFSHandler) SimpleFSGetArchiveStatus(ctx context.Context) (
   936  	status keybase1.SimpleFSArchiveStatus, err error) {
   937  	cli, err := s.client(ctx)
   938  	if err != nil {
   939  		return keybase1.SimpleFSArchiveStatus{}, nil
   940  	}
   941  	ctx, cancel := s.wrapContextWithTimeout(ctx)
   942  	defer cancel()
   943  	return cli.SimpleFSGetArchiveStatus(ctx)
   944  }