github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/repo/buildrepo/build.go (about) 1 // Package buildrepo initializes a qri repo 2 package buildrepo 3 4 import ( 5 "context" 6 "fmt" 7 "path/filepath" 8 "strings" 9 10 golog "github.com/ipfs/go-log" 11 "github.com/qri-io/qfs" 12 "github.com/qri-io/qfs/muxfs" 13 "github.com/qri-io/qri/auth/key" 14 "github.com/qri-io/qri/config" 15 "github.com/qri-io/qri/dscache" 16 "github.com/qri-io/qri/event" 17 "github.com/qri-io/qri/logbook" 18 "github.com/qri-io/qri/profile" 19 "github.com/qri-io/qri/repo" 20 fsrepo "github.com/qri-io/qri/repo/fs" 21 ) 22 23 var log = golog.Logger("buildrepo") 24 25 // Options provides additional fields to new 26 type Options struct { 27 Profiles profile.Store 28 Keystore key.Store 29 Filesystem *muxfs.Mux 30 Logbook *logbook.Book 31 Dscache *dscache.Dscache 32 Bus event.Bus 33 } 34 35 // New is the canonical method for building a repo 36 func New(ctx context.Context, path string, cfg *config.Config, opts ...func(o *Options)) (repo.Repo, error) { 37 o := &Options{} 38 for _, opt := range opts { 39 opt(o) 40 } 41 42 // Don't create a localstore with the empty path, this will use the current directory 43 if cfg.Repo.Type == "fs" && cfg.Path() == "" { 44 return nil, fmt.Errorf("buildRepo.New using filesystem requires non-empty path") 45 } 46 47 var err error 48 if o.Keystore == nil { 49 log.Debug("buildrepo.New: creating keystore") 50 if o.Keystore, err = key.NewStore(cfg); err != nil { 51 return nil, err 52 } 53 } 54 if o.Profiles == nil { 55 log.Debug("buildrepo.New: creating profiles") 56 if o.Profiles, err = profile.NewStore(ctx, cfg, o.Keystore); err != nil { 57 return nil, err 58 } 59 } 60 if o.Filesystem == nil { 61 log.Debug("buildrepo.New: creating filesystem") 62 if o.Filesystem, err = NewFilesystem(ctx, cfg); err != nil { 63 return nil, err 64 } 65 } 66 if o.Bus == nil { 67 log.Debug("buildrepo.New: creating bus") 68 o.Bus = event.NilBus 69 } 70 71 pro := o.Profiles.Owner(ctx) 72 73 log.Debug("buildrepo.New: profile %q, %q", pro.Peername, pro.ID) 74 switch cfg.Repo.Type { 75 case "fs": 76 if o.Logbook == nil { 77 if o.Logbook, err = newLogbook(o.Filesystem, o.Bus, pro, path); err != nil { 78 return nil, err 79 } 80 } 81 if o.Dscache == nil { 82 if o.Dscache, err = newDscache(ctx, o.Filesystem, o.Bus, o.Logbook, pro.Peername, path); err != nil { 83 return nil, err 84 } 85 } 86 87 return fsrepo.NewRepo(ctx, path, o.Filesystem, o.Logbook, o.Dscache, o.Profiles, o.Bus) 88 case "mem": 89 return repo.NewMemRepo(ctx, o.Filesystem, o.Logbook, o.Dscache, o.Profiles, o.Bus) 90 default: 91 return nil, fmt.Errorf("unknown repo type: %s", cfg.Repo.Type) 92 } 93 } 94 95 // NewFilesystem creates a qfs.Filesystem from configuration 96 func NewFilesystem(ctx context.Context, cfg *config.Config) (*muxfs.Mux, error) { 97 qriPath := filepath.Dir(cfg.Path()) 98 99 for i, fsCfg := range cfg.Filesystems { 100 if fsCfg.Type == "ipfs" { 101 if path, ok := fsCfg.Config["path"].(string); ok { 102 if !filepath.IsAbs(path) { 103 // resolve relative filepaths 104 cfg.Filesystems[i].Config["path"] = filepath.Join(qriPath, path) 105 } 106 } 107 } 108 } 109 110 if cfg.Repo.Type == "mem" { 111 hasMemType := false 112 for _, fsCfg := range cfg.Filesystems { 113 if fsCfg.Type == "mem" { 114 hasMemType = true 115 } 116 } 117 if !hasMemType { 118 cfg.Filesystems = append(cfg.Filesystems, qfs.Config{Type: "mem"}) 119 } 120 } 121 122 return muxfs.New(ctx, cfg.Filesystems) 123 } 124 125 func newLogbook(fs qfs.Filesystem, bus event.Bus, pro *profile.Profile, repoPath string) (book *logbook.Book, err error) { 126 logbookPath := filepath.Join(repoPath, "logbook.qfb") 127 return logbook.NewJournal(*pro, bus, fs, logbookPath) 128 } 129 130 func newDscache(ctx context.Context, fs qfs.Filesystem, bus event.Bus, book *logbook.Book, username, repoPath string) (*dscache.Dscache, error) { 131 // This seems to be a bug, the repoPath does not end in "qri" in some tests. 132 if !strings.HasSuffix(repoPath, "qri") { 133 return nil, fmt.Errorf("invalid repo path: %q", repoPath) 134 } 135 dscachePath := filepath.Join(repoPath, "dscache.qfb") 136 return dscache.NewDscache(ctx, fs, bus, username, dscachePath), nil 137 }