github.com/pachyderm/pachyderm@v1.13.4/src/server/pfs/fuse/fuse.go (about)

     1  package fuse
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"os/signal"
     7  	pathpkg "path"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/hanwen/go-fuse/v2/fs"
    12  
    13  	"github.com/pachyderm/pachyderm/src/client"
    14  	"github.com/pachyderm/pachyderm/src/client/pkg/errors"
    15  	"github.com/pachyderm/pachyderm/src/server/pkg/progress"
    16  	"github.com/pachyderm/pachyderm/src/server/pkg/uuid"
    17  )
    18  
    19  // Mount pfs to target, opts may be left nil.
    20  func Mount(c *client.APIClient, target string, opts *Options) (retErr error) {
    21  	if err := opts.validate(c); err != nil {
    22  		return err
    23  	}
    24  	commits := make(map[string]string)
    25  	for repo, branch := range opts.getBranches() {
    26  		if uuid.IsUUIDWithoutDashes(branch) {
    27  			commits[repo] = branch
    28  		}
    29  	}
    30  	rootDir, err := ioutil.TempDir("", "pfs")
    31  	if err != nil {
    32  		return errors.WithStack(err)
    33  	}
    34  	defer func() {
    35  		if err := os.RemoveAll(rootDir); err != nil && retErr == nil {
    36  			retErr = errors.WithStack(err)
    37  		}
    38  	}()
    39  	root, err := newLoopbackRoot(rootDir, target, c, opts)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	server, err := fs.Mount(target, root, opts.getFuse())
    44  	if err != nil {
    45  		return errors.WithStack(err)
    46  	}
    47  	sigChan := make(chan os.Signal, 1)
    48  	signal.Notify(sigChan, os.Interrupt)
    49  	go func() {
    50  		select {
    51  		case <-sigChan:
    52  		case <-opts.getUnmount():
    53  		}
    54  		server.Unmount()
    55  	}()
    56  	server.Serve()
    57  	pfcs := make(map[string]client.PutFileClient)
    58  	pfc := func(repo string) (client.PutFileClient, error) {
    59  		if pfc, ok := pfcs[repo]; ok {
    60  			return pfc, nil
    61  		}
    62  		pfc, err := c.NewPutFileClient()
    63  		if err != nil {
    64  			return nil, err
    65  		}
    66  		pfcs[repo] = pfc
    67  		return pfc, nil
    68  	}
    69  	defer func() {
    70  		for _, pfc := range pfcs {
    71  			if err := pfc.Close(); err != nil && retErr == nil {
    72  				retErr = err
    73  			}
    74  		}
    75  	}()
    76  	for path, state := range root.files {
    77  		if state != dirty {
    78  			continue
    79  		}
    80  		parts := strings.Split(path, "/")
    81  		pfc, err := pfc(parts[0])
    82  		if err != nil {
    83  			return err
    84  		}
    85  		if err := func() (retErr error) {
    86  			f, err := progress.Open(filepath.Join(root.rootPath, path))
    87  			if err != nil {
    88  				if errors.Is(err, os.ErrNotExist) {
    89  					return pfc.DeleteFile(parts[0], root.branch(parts[0]), pathpkg.Join(parts[1:]...))
    90  				}
    91  				return errors.WithStack(err)
    92  			}
    93  			defer func() {
    94  				if err := f.Close(); err != nil && retErr == nil {
    95  					retErr = errors.WithStack(err)
    96  				}
    97  			}()
    98  			if _, err := pfc.PutFileOverwrite(parts[0], root.branch(parts[0]),
    99  				pathpkg.Join(parts[1:]...), f, 0); err != nil {
   100  				return err
   101  			}
   102  			return nil
   103  		}(); err != nil {
   104  			return err
   105  		}
   106  	}
   107  	return nil
   108  }