diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index dd244407a..0c31ce01a 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -110,11 +110,11 @@ func daemonFunc(req cmds.Request, res cmds.Response) { // let the user know we're going. fmt.Printf("Initializing daemon...\n") - ctx := req.Context() + ctx := req.InvocContext() go func() { select { - case <-ctx.Context.Done(): + case <-req.Context().Done(): fmt.Println("Received interrupt signal, shutting down...") } }() @@ -141,8 +141,8 @@ func daemonFunc(req cmds.Request, res cmds.Response) { // configured. Consider moving this into a config helper method // `IsInitialized` where the quality of the signal can be improved over // time, and many call-sites can benefit. - if !util.FileExists(req.Context().ConfigRoot) { - err := initWithDefaults(os.Stdout, req.Context().ConfigRoot) + if !util.FileExists(req.InvocContext().ConfigRoot) { + err := initWithDefaults(os.Stdout, req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -152,7 +152,7 @@ func daemonFunc(req cmds.Request, res cmds.Response) { // acquire the repo lock _before_ constructing a node. we need to make // sure we are permitted to access the resources (datastore, etc.) - repo, err := fsrepo.Open(req.Context().ConfigRoot) + repo, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -190,7 +190,7 @@ func daemonFunc(req cmds.Request, res cmds.Response) { nb.SetRouting(corerouting.SupernodeClient(infos...)) } - node, err := nb.Build(ctx.Context) + node, err := nb.Build(req.Context()) if err != nil { log.Error("error from node construction: ", err) res.SetError(err, cmds.ErrNormal) @@ -205,13 +205,13 @@ func daemonFunc(req cmds.Request, res cmds.Response) { node.Close() select { - case <-ctx.Context.Done(): + case <-req.Context().Done(): log.Info("Gracefully shut down daemon") default: } }() - req.Context().ConstructNode = func() (*core.IpfsNode, error) { + req.InvocContext().ConstructNode = func() (*core.IpfsNode, error) { return node, nil } @@ -258,7 +258,7 @@ func daemonFunc(req cmds.Request, res cmds.Response) { // serveHTTPApi collects options, creates listener, prints status message and starts serving requests func serveHTTPApi(req cmds.Request) (error, <-chan error) { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { return fmt.Errorf("serveHTTPApi: GetConfig() failed: %s", err), nil } @@ -299,7 +299,7 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) { }, }) var opts = []corehttp.ServeOption{ - corehttp.CommandsOption(*req.Context()), + corehttp.CommandsOption(*req.InvocContext()), corehttp.WebUIOption, apiGw.ServeOption(), corehttp.VersionOption(), @@ -313,7 +313,7 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) { opts = append(opts, corehttp.RedirectOption("", cfg.Gateway.RootRedirect)) } - node, err := req.Context().ConstructNode() + node, err := req.InvocContext().ConstructNode() if err != nil { return fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err), nil } @@ -341,7 +341,7 @@ func printSwarmAddrs(node *core.IpfsNode) { // serveHTTPGateway collects options, creates listener, prints status message and starts serving requests func serveHTTPGateway(req cmds.Request) (error, <-chan error) { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { return fmt.Errorf("serveHTTPGateway: GetConfig() failed: %s", err), nil } @@ -382,7 +382,7 @@ func serveHTTPGateway(req cmds.Request) (error, <-chan error) { opts = append(opts, corehttp.RedirectOption("", cfg.Gateway.RootRedirect)) } - node, err := req.Context().ConstructNode() + node, err := req.InvocContext().ConstructNode() if err != nil { return fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err), nil } @@ -397,7 +397,7 @@ func serveHTTPGateway(req cmds.Request) (error, <-chan error) { //collects options and opens the fuse mountpoint func mountFuse(req cmds.Request) error { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { return fmt.Errorf("mountFuse: GetConfig() failed: %s", err) } @@ -418,7 +418,7 @@ func mountFuse(req cmds.Request) error { nsdir = cfg.Mounts.IPNS } - node, err := req.Context().ConstructNode() + node, err := req.InvocContext().ConstructNode() if err != nil { return fmt.Errorf("mountFuse: ConstructNode() failed: %s", err) } diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 46f8fd24b..07f1dae88 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -34,7 +34,7 @@ var initCmd = &cmds.Command{ // TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"), }, PreRun: func(req cmds.Request) error { - daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot) + daemonLocked, err := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) if err != nil { return err } @@ -48,7 +48,7 @@ var initCmd = &cmds.Command{ return nil }, Run: func(req cmds.Request, res cmds.Response) { - if req.Context().Online { + if req.InvocContext().Online { res.SetError(errors.New("init must be run offline only!"), cmds.ErrNormal) return } @@ -69,7 +69,7 @@ var initCmd = &cmds.Command{ nBitsForKeypair = nBitsForKeypairDefault } - if err := doInit(os.Stdout, req.Context().ConfigRoot, force, nBitsForKeypair); err != nil { + if err := doInit(os.Stdout, req.InvocContext().ConfigRoot, force, nBitsForKeypair); err != nil { res.SetError(err, cmds.ErrNormal) return } diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 319c223d9..c6c6da8e9 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -192,12 +192,12 @@ func (i *cmdInvocation) constructNodeFunc(ctx context.Context) func() (*core.Ipf return nil, errors.New("constructing node without a request") } - cmdctx := i.req.Context() + cmdctx := i.req.InvocContext() if cmdctx == nil { return nil, errors.New("constructing node without a request context") } - r, err := fsrepo.Open(i.req.Context().ConfigRoot) + r, err := fsrepo.Open(i.req.InvocContext().ConfigRoot) if err != nil { // repo is owned by the node return nil, err } @@ -238,7 +238,7 @@ func (i *cmdInvocation) Parse(ctx context.Context, args []string) error { log.Debugf("config path is %s", repoPath) // this sets up the function that will initialize the config lazily. - cmdctx := i.req.Context() + cmdctx := i.req.InvocContext() cmdctx.ConfigRoot = repoPath cmdctx.LoadConfig = loadConfig // this sets up the function that will initialize the node @@ -279,10 +279,13 @@ func callPreCommandHooks(ctx context.Context, details cmdDetails, req cmds.Reque } func callCommand(ctx context.Context, req cmds.Request, root *cmds.Command, cmd *cmds.Command) (cmds.Response, error) { - log.Info(config.EnvDir, " ", req.Context().ConfigRoot) + log.Info(config.EnvDir, " ", req.InvocContext().ConfigRoot) var res cmds.Response - req.Context().Context = ctx + err := req.SetRootContext(ctx) + if err != nil { + return nil, err + } details, err := commandDetails(req.Path(), root) if err != nil { @@ -309,7 +312,7 @@ func callCommand(ctx context.Context, req cmds.Request, root *cmds.Command, cmd if useDaemon { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { return nil, err } @@ -335,13 +338,11 @@ func callCommand(ctx context.Context, req cmds.Request, root *cmds.Command, cmd } else { log.Debug("Executing command locally") - ctx, err := cmds.GetContext(ctx, req) + err := req.SetRootContext(ctx) if err != nil { return nil, err } - req.Context().Context = ctx - // Okay!!!!! NOW we can call the command. res = root.Call(req) @@ -399,7 +400,7 @@ func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.C // at this point need to know whether daemon is running. we defer // to this point so that some commands dont open files unnecessarily. - daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot) + daemonLocked, err := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) if err != nil { return false, err } diff --git a/cmd/ipfswatch/main.go b/cmd/ipfswatch/main.go index 87570e356..3a4fb8f09 100644 --- a/cmd/ipfswatch/main.go +++ b/cmd/ipfswatch/main.go @@ -185,8 +185,6 @@ func IsHidden(path string) bool { func cmdCtx(node *core.IpfsNode, repoPath string) commands.Context { return commands.Context{ - // TODO deprecate this shit - Context: context.Background(), Online: true, ConfigRoot: repoPath, LoadConfig: func(path string) (*config.Config, error) { diff --git a/commands/http/client.go b/commands/http/client.go index a34c89d1a..9d21c9d5e 100644 --- a/commands/http/client.go +++ b/commands/http/client.go @@ -84,7 +84,7 @@ func (c *client) Send(req cmds.Request) (cmds.Response, error) { ec := make(chan error, 1) rc := make(chan cmds.Response, 1) - dc := req.Context().Context.Done() + dc := req.Context().Done() go func() { httpRes, err := http.DefaultClient.Do(httpReq) @@ -181,7 +181,7 @@ func getResponse(httpRes *http.Response, req cmds.Request) (cmds.Response, error dec := json.NewDecoder(httpRes.Body) outputType := reflect.TypeOf(req.Command().Type) - ctx := req.Context().Context + ctx := req.Context() for { var v interface{} diff --git a/commands/http/handler.go b/commands/http/handler.go index 22886ef25..8d44b8601 100644 --- a/commands/http/handler.go +++ b/commands/http/handler.go @@ -106,18 +106,14 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - ctx, err := cmds.GetContext(node.Context(), req) + //ps: take note of the name clash - commands.Context != context.Context + req.SetInvocContext(i.ctx) + err = req.SetRootContext(node.Context()) if err != nil { - err = fmt.Errorf("error parsing timeout option: %s", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } - //ps: take note of the name clash - commands.Context != context.Context - cmdctx := i.ctx - cmdctx.Context = ctx - req.SetContext(cmdctx) - // call the command res := i.root.Call(req) diff --git a/commands/request.go b/commands/request.go index d04b0dbdd..11e556754 100644 --- a/commands/request.go +++ b/commands/request.go @@ -19,10 +19,6 @@ import ( type OptMap map[string]interface{} type Context struct { - // this Context is temporary. Will be replaced soon, as we get - // rid of this variable entirely. - Context context.Context - Online bool ConfigRoot string @@ -76,8 +72,10 @@ type Request interface { SetArguments([]string) Files() files.File SetFiles(files.File) - Context() *Context - SetContext(Context) + Context() context.Context + SetRootContext(context.Context) error + InvocContext() *Context + SetInvocContext(Context) Command() *Command Values() map[string]interface{} Stdin() io.Reader @@ -92,6 +90,7 @@ type request struct { files files.File cmd *Command ctx Context + rctx context.Context optionDefs map[string]Option values map[string]interface{} stdin io.Reader @@ -131,6 +130,16 @@ func (r *request) Options() OptMap { return output } +func (r *request) SetRootContext(ctx context.Context) error { + ctx, err := getContext(ctx, r) + if err != nil { + return err + } + + r.rctx = ctx + return nil +} + // SetOption sets the value of the option for given name. func (r *request) SetOption(name string, val interface{}) { // find the option with the specified name @@ -174,11 +183,37 @@ func (r *request) SetFiles(f files.File) { r.files = f } -func (r *request) Context() *Context { +func (r *request) Context() context.Context { + return r.rctx +} + +func getContext(base context.Context, req Request) (context.Context, error) { + tout, found, err := req.Option("timeout").String() + if err != nil { + return nil, fmt.Errorf("error parsing timeout option: %s", err) + } + + var ctx context.Context + if found { + duration, err := time.ParseDuration(tout) + if err != nil { + return nil, fmt.Errorf("error parsing timeout option: %s", err) + } + + tctx, _ := context.WithTimeout(base, duration) + ctx = tctx + } else { + cctx, _ := context.WithCancel(base) + ctx = cctx + } + return ctx, nil +} + +func (r *request) InvocContext() *Context { return &r.ctx } -func (r *request) SetContext(ctx Context) { +func (r *request) SetInvocContext(ctx Context) { r.ctx = ctx } @@ -275,22 +310,26 @@ func NewEmptyRequest() (Request, error) { // NewRequest returns a request initialized with given arguments // An non-nil error will be returned if the provided option values are invalid func NewRequest(path []string, opts OptMap, args []string, file files.File, cmd *Command, optDefs map[string]Option) (Request, error) { - if path == nil { - path = make([]string, 0) - } if opts == nil { opts = make(OptMap) } - if args == nil { - args = make([]string, 0) - } if optDefs == nil { optDefs = make(map[string]Option) } - ctx := Context{Context: context.TODO()} + ctx := Context{} values := make(map[string]interface{}) - req := &request{path, opts, args, file, cmd, ctx, optDefs, values, os.Stdin} + req := &request{ + path: path, + options: opts, + arguments: args, + files: file, + cmd: cmd, + ctx: ctx, + optionDefs: optDefs, + values: values, + stdin: os.Stdin, + } err := req.ConvertOptions() if err != nil { return nil, err @@ -298,25 +337,3 @@ func NewRequest(path []string, opts OptMap, args []string, file files.File, cmd return req, nil } - -func GetContext(base context.Context, req Request) (context.Context, error) { - tout, found, err := req.Option("timeout").String() - if err != nil { - return nil, fmt.Errorf("error parsing timeout option: %s", err) - } - - var ctx context.Context - if found { - duration, err := time.ParseDuration(tout) - if err != nil { - return nil, fmt.Errorf("error parsing timeout option: %s", err) - } - - tctx, _ := context.WithTimeout(base, duration) - ctx = tctx - } else { - cctx, _ := context.WithCancel(base) - ctx = cctx - } - return ctx, nil -} diff --git a/core/commands/add.go b/core/commands/add.go index 327b47b4d..a3e438e32 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -88,7 +88,7 @@ remains to be implemented. return nil }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go index daa9ae0cd..3d2288af6 100644 --- a/core/commands/bitswap.go +++ b/core/commands/bitswap.go @@ -33,7 +33,7 @@ Print out all blocks currently on the bitswap wantlist for the local peer`, }, Type: KeyList{}, Run: func(req cmds.Request, res cmds.Response) { - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -78,7 +78,7 @@ var bitswapStatCmd = &cmds.Command{ }, Type: bitswap.Stat{}, Run: func(req cmds.Request, res cmds.Response) { - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/block.go b/core/commands/block.go index 6346e53ac..20e3f94ba 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -114,7 +114,7 @@ It reads from stdin, and is a base58 encoded multihash. cmds.FileArg("data", true, false, "The data to be stored as an IPFS block").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -162,7 +162,7 @@ It reads from stdin, and is a base58 encoded multihash. } func getBlockForKey(req cmds.Request, skey string) (*blocks.Block, error) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { return nil, err } @@ -177,7 +177,7 @@ func getBlockForKey(req cmds.Request, skey string) (*blocks.Block, error) { } k := key.Key(h) - b, err := n.Blocks.GetBlock(req.Context().Context, k) + b, err := n.Blocks.GetBlock(req.Context(), k) if err != nil { return nil, err } diff --git a/core/commands/bootstrap.go b/core/commands/bootstrap.go index 919a86179..c9134e6d4 100644 --- a/core/commands/bootstrap.go +++ b/core/commands/bootstrap.go @@ -66,7 +66,7 @@ in the bootstrap list). return } - r, err := fsrepo.Open(req.Context().ConfigRoot) + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -142,7 +142,7 @@ var bootstrapRemoveCmd = &cmds.Command{ return } - r, err := fsrepo.Open(req.Context().ConfigRoot) + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -191,7 +191,7 @@ var bootstrapListCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - r, err := fsrepo.Open(req.Context().ConfigRoot) + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/cat.go b/core/commands/cat.go index 2f888dac5..8da37c576 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -27,13 +27,13 @@ it contains. cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return } - readers, length, err := cat(req.Context().Context, node, req.Arguments()) + readers, length, err := cat(req.Context(), node, req.Arguments()) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/config.go b/core/commands/config.go index d9eb174b7..6087b9267 100644 --- a/core/commands/config.go +++ b/core/commands/config.go @@ -65,7 +65,7 @@ Set the value of the 'datastore.path' key: args := req.Arguments() key := args[0] - r, err := fsrepo.Open(req.Context().ConfigRoot) + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -141,7 +141,7 @@ included in the output of this command. }, Run: func(req cmds.Request, res cmds.Response) { - filename, err := config.Filename(req.Context().ConfigRoot) + filename, err := config.Filename(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -166,7 +166,7 @@ variable set to your preferred text editor. }, Run: func(req cmds.Request, res cmds.Response) { - filename, err := config.Filename(req.Context().ConfigRoot) + filename, err := config.Filename(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -192,7 +192,7 @@ can't be undone. cmds.FileArg("file", true, false, "The file to use as the new config"), }, Run: func(req cmds.Request, res cmds.Response) { - r, err := fsrepo.Open(req.Context().ConfigRoot) + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/dht.go b/core/commands/dht.go index 433f9fe01..1f081ba91 100644 --- a/core/commands/dht.go +++ b/core/commands/dht.go @@ -45,7 +45,7 @@ var queryDhtCmd = &cmds.Command{ cmds.BoolOption("verbose", "v", "Write extra information"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -58,7 +58,7 @@ var queryDhtCmd = &cmds.Command{ } events := make(chan *notif.QueryEvent) - ctx := notif.RegisterForQueryEvents(req.Context().Context, events) + ctx := notif.RegisterForQueryEvents(req.Context(), events) closestPeers, err := dht.GetClosestPeers(ctx, key.Key(req.Arguments()[0])) if err != nil { @@ -152,7 +152,7 @@ FindProviders will return a list of peers who are able to provide the value requ cmds.BoolOption("verbose", "v", "Write extra information"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -170,7 +170,7 @@ FindProviders will return a list of peers who are able to provide the value requ res.SetOutput((<-chan interface{})(outChan)) events := make(chan *notif.QueryEvent) - ctx := notif.RegisterForQueryEvents(req.Context().Context, events) + ctx := notif.RegisterForQueryEvents(req.Context(), events) pchan := dht.FindProvidersAsync(ctx, key.B58KeyDecode(req.Arguments()[0]), numProviders) go func() { @@ -265,7 +265,7 @@ var findPeerDhtCmd = &cmds.Command{ cmds.StringArg("peerID", true, true, "The peer to search for"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -287,7 +287,7 @@ var findPeerDhtCmd = &cmds.Command{ res.SetOutput((<-chan interface{})(outChan)) events := make(chan *notif.QueryEvent) - ctx := notif.RegisterForQueryEvents(req.Context().Context, events) + ctx := notif.RegisterForQueryEvents(req.Context(), events) go func() { defer close(outChan) @@ -375,7 +375,7 @@ GetValue will return the value stored in the dht at the given key. cmds.BoolOption("verbose", "v", "Write extra information"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -391,7 +391,7 @@ GetValue will return the value stored in the dht at the given key. res.SetOutput((<-chan interface{})(outChan)) events := make(chan *notif.QueryEvent) - ctx := notif.RegisterForQueryEvents(req.Context().Context, events) + ctx := notif.RegisterForQueryEvents(req.Context(), events) go func() { defer close(outChan) @@ -483,7 +483,7 @@ PutValue will store the given key value pair in the dht. cmds.BoolOption("verbose", "v", "Write extra information"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -499,7 +499,7 @@ PutValue will store the given key value pair in the dht. res.SetOutput((<-chan interface{})(outChan)) events := make(chan *notif.QueryEvent) - ctx := notif.RegisterForQueryEvents(req.Context().Context, events) + ctx := notif.RegisterForQueryEvents(req.Context(), events) key := key.B58KeyDecode(req.Arguments()[0]) data := req.Arguments()[1] diff --git a/core/commands/diag.go b/core/commands/diag.go index 987db1f1b..4d3a82b25 100644 --- a/core/commands/diag.go +++ b/core/commands/diag.go @@ -90,7 +90,7 @@ that consume the dot format to generate graphs of the network. }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/dns.go b/core/commands/dns.go index e24b6a483..6ff2d6465 100644 --- a/core/commands/dns.go +++ b/core/commands/dns.go @@ -62,7 +62,7 @@ The resolver will give: if recursive { depth = namesys.DefaultDepthLimit } - output, err := resolver.ResolveN(req.Context().Context, name, depth) + output, err := resolver.ResolveN(req.Context(), name, depth) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/get.go b/core/commands/get.go index 39fced25c..3ab7763f6 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -59,7 +59,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. return } - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -69,9 +69,9 @@ may also specify the level of compression by specifying '-l=<1-9>'. var reader io.Reader if archive, _, _ := req.Option("archive").Bool(); !archive && cmplvl != gzip.NoCompression { // only use this when the flag is '-C' without '-a' - reader, err = getZip(req.Context().Context, node, p, cmplvl) + reader, err = getZip(req.Context(), node, p, cmplvl) } else { - reader, err = get(req.Context().Context, node, p, cmplvl) + reader, err = get(req.Context(), node, p, cmplvl) } if err != nil { res.SetError(err, cmds.ErrNormal) diff --git a/core/commands/id.go b/core/commands/id.go index 31af08067..407eea138 100644 --- a/core/commands/id.go +++ b/core/commands/id.go @@ -56,7 +56,7 @@ ipfs id supports the format option for output with the following keys: cmds.StringOption("f", "format", "optional output format"), }, Run: func(req cmds.Request, res cmds.Response) { - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -86,7 +86,7 @@ ipfs id supports the format option for output with the following keys: return } - p, err := node.Routing.FindPeer(req.Context().Context, id) + p, err := node.Routing.FindPeer(req.Context(), id) if err == kb.ErrLookupFailure { res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient) return diff --git a/core/commands/ipns.go b/core/commands/ipns.go index 50bcd6304..0c9320226 100644 --- a/core/commands/ipns.go +++ b/core/commands/ipns.go @@ -47,7 +47,7 @@ Resolve the value of another name: }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -81,7 +81,7 @@ Resolve the value of another name: } resolver := namesys.NewRoutingResolver(n.Routing) - output, err := resolver.ResolveN(n.Context(), name, depth) + output, err := resolver.ResolveN(req.Context(), name, depth) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/log.go b/core/commands/log.go index aa819c625..ccb8064a3 100644 --- a/core/commands/log.go +++ b/core/commands/log.go @@ -80,7 +80,7 @@ var logTailCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - path := fmt.Sprintf("%s/logs/events.log", req.Context().ConfigRoot) + path := fmt.Sprintf("%s/logs/events.log", req.InvocContext().ConfigRoot) outChan := make(chan interface{}) @@ -99,7 +99,7 @@ var logTailCmd = &cmds.Command{ } defer t.Stop() - done := req.Context().Context.Done() + done := req.Context().Done() for line := range t.Lines { // return when context closes diff --git a/core/commands/ls.go b/core/commands/ls.go index 27f11d1da..921155321 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -50,7 +50,7 @@ it contains, with the following format: cmds.BoolOption("headers", "", "Print table headers (Hash, Name, Size)"), }, Run: func(req cmds.Request, res cmds.Response) { - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -66,7 +66,7 @@ it contains, with the following format: var dagnodes []*merkledag.Node for _, fpath := range paths { - dagnode, err := core.Resolve(req.Context().Context, node, path.Path(fpath)) + dagnode, err := core.Resolve(req.Context(), node, path.Path(fpath)) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -81,7 +81,7 @@ it contains, with the following format: Links: make([]LsLink, len(dagnode.Links)), } for j, link := range dagnode.Links { - ctx, cancel := context.WithTimeout(req.Context().Context, time.Minute) + ctx, cancel := context.WithTimeout(req.Context(), time.Minute) defer cancel() link.Node, err = link.GetNode(ctx, node.DAG) if err != nil { diff --git a/core/commands/mount_unix.go b/core/commands/mount_unix.go index f475d62d8..c3410a6f9 100644 --- a/core/commands/mount_unix.go +++ b/core/commands/mount_unix.go @@ -97,13 +97,13 @@ baz cmds.StringOption("ipns-path", "n", "The path where IPNS should be mounted"), }, Run: func(req cmds.Request, res cmds.Response) { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { res.SetError(err, cmds.ErrNormal) return } - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/object.go b/core/commands/object.go index cb35e4a85..c4976f63f 100644 --- a/core/commands/object.go +++ b/core/commands/object.go @@ -93,14 +93,14 @@ output is the raw data of the object. cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return } fpath := path.Path(req.Arguments()[0]) - node, err := core.Resolve(req.Context().Context, n, fpath) + node, err := core.Resolve(req.Context(), n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -123,14 +123,14 @@ multihash. cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return } fpath := path.Path(req.Arguments()[0]) - node, err := core.Resolve(req.Context().Context, n, fpath) + node, err := core.Resolve(req.Context(), n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -182,7 +182,7 @@ This command outputs data in the following encodings: cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -190,7 +190,7 @@ This command outputs data in the following encodings: fpath := path.Path(req.Arguments()[0]) - object, err := core.Resolve(req.Context().Context, n, fpath) + object, err := core.Resolve(req.Context(), n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -248,7 +248,7 @@ var objectStatCmd = &cmds.Command{ cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -256,7 +256,7 @@ var objectStatCmd = &cmds.Command{ fpath := path.Path(req.Arguments()[0]) - object, err := core.Resolve(req.Context().Context, n, fpath) + object, err := core.Resolve(req.Context(), n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -335,7 +335,7 @@ and then run cmds.StringOption("inputenc", "Encoding type of input data, either \"protobuf\" or \"json\""), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -397,7 +397,7 @@ Available templates: cmds.StringArg("template", false, false, "optional template to use"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -461,7 +461,7 @@ resulting object hash. }, Type: Object{}, Run: func(req cmds.Request, res cmds.Response) { - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -473,7 +473,7 @@ resulting object hash. return } - ctx, cancel := context.WithTimeout(req.Context().Context, time.Second*30) + ctx, cancel := context.WithTimeout(req.Context(), time.Second*30) rnode, err := nd.DAG.Get(ctx, rhash) if err != nil { res.SetError(err, cmds.ErrNormal) @@ -535,7 +535,7 @@ func appendDataCaller(req cmds.Request, root *dag.Node) (key.Key, error) { return "", fmt.Errorf("not enough arguments for set-data") } - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { return "", err } @@ -555,7 +555,7 @@ func setDataCaller(req cmds.Request, root *dag.Node) (key.Key, error) { return "", fmt.Errorf("not enough arguments for set-data") } - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { return "", err } @@ -575,7 +575,7 @@ func rmLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) { return "", fmt.Errorf("not enough arguments for rm-link") } - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { return "", err } @@ -600,7 +600,7 @@ func addLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) { return "", fmt.Errorf("not enough arguments for add-link") } - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { return "", err } @@ -610,7 +610,7 @@ func addLinkCaller(req cmds.Request, root *dag.Node) (key.Key, error) { parts := strings.Split(path, "/") - nnode, err := insertNodeAtPath(req.Context().Context, nd.DAG, root, parts, childk) + nnode, err := insertNodeAtPath(req.Context(), nd.DAG, root, parts, childk) if err != nil { return "", err } diff --git a/core/commands/pin.go b/core/commands/pin.go index 0e3726e9f..33258b832 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -44,7 +44,7 @@ on disk. }, Type: PinOutput{}, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -61,11 +61,11 @@ on disk. } go func() { - <-req.Context().Context.Done() + <-req.Context().Done() log.Error("CONTEXT IS OVER!") }() - added, err := corerepo.Pin(n, req.Context().Context, req.Arguments(), recursive) + added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -114,7 +114,7 @@ collected if needed. }, Type: PinOutput{}, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -130,7 +130,7 @@ collected if needed. recursive = false // default } - removed, err := corerepo.Unpin(n, req.Context().Context, req.Arguments(), recursive) + removed, err := corerepo.Unpin(n, req.Context(), req.Arguments(), recursive) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -182,7 +182,7 @@ Defaults to "direct". cmds.BoolOption("quiet", "q", "Write just hashes of objects"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/ping.go b/core/commands/ping.go index fa9974428..2b4ff2dbf 100644 --- a/core/commands/ping.go +++ b/core/commands/ping.go @@ -75,8 +75,8 @@ trip latency information. }, }, Run: func(req cmds.Request, res cmds.Response) { - ctx := req.Context().Context - n, err := req.Context().GetNode() + ctx := req.Context() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/publish.go b/core/commands/publish.go index b89214e17..c1798e15d 100644 --- a/core/commands/publish.go +++ b/core/commands/publish.go @@ -51,7 +51,7 @@ Publish an to another public key (not implemented): }, Run: func(req cmds.Request, res cmds.Response) { log.Debug("Begin Publish") - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -90,7 +90,7 @@ Publish an to another public key (not implemented): // TODO n.Keychain.Get(name).PrivKey // TODO(cryptix): is req.Context().Context a child of n.Context()? - output, err := publish(req.Context().Context, n, n.PrivateKey, path.Path(pstr)) + output, err := publish(req.Context(), n, n.PrivateKey, path.Path(pstr)) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/refs.go b/core/commands/refs.go index 703a6b679..792d59ae1 100644 --- a/core/commands/refs.go +++ b/core/commands/refs.go @@ -56,8 +56,8 @@ Note: list all refs recursively with -r. cmds.BoolOption("recursive", "r", "Recursively list links of child nodes"), }, Run: func(req cmds.Request, res cmds.Response) { - ctx := req.Context().Context - n, err := req.Context().GetNode() + ctx := req.Context() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -156,8 +156,8 @@ Displays the hashes of all local objects. }, Run: func(req cmds.Request, res cmds.Response) { - ctx := req.Context().Context - n, err := req.Context().GetNode() + ctx := req.Context() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/repo.go b/core/commands/repo.go index 8ae0d0408..8ad0c7296 100644 --- a/core/commands/repo.go +++ b/core/commands/repo.go @@ -37,13 +37,13 @@ order to reclaim hard disk space. cmds.BoolOption("quiet", "q", "Write minimal output"), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return } - gcOutChan, err := corerepo.GarbageCollectAsync(n, req.Context().Context) + gcOutChan, err := corerepo.GarbageCollectAsync(n, req.Context()) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/resolve.go b/core/commands/resolve.go index 9e8845caf..e8c25a4c1 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -57,7 +57,7 @@ Resolve the value of another name recursively: }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -78,7 +78,7 @@ Resolve the value of another name recursively: depth = namesys.DefaultDepthLimit } - output, err := n.Namesys.ResolveN(n.Context(), name, depth) + output, err := n.Namesys.ResolveN(req.Context(), name, depth) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/stat.go b/core/commands/stat.go index f5479019f..5e222fa04 100644 --- a/core/commands/stat.go +++ b/core/commands/stat.go @@ -40,7 +40,7 @@ var statBwCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - nd, err := req.Context().GetNode() + nd, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -121,7 +121,7 @@ var statBwCmd = &cmds.Command{ } select { case <-time.After(interval): - case <-req.Context().Context.Done(): + case <-req.Context().Done(): return } } diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 3bcfb30c8..a0018bbf4 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -61,7 +61,7 @@ ipfs swarm peers lists the set of peers this node is connected to. Run: func(req cmds.Request, res cmds.Response) { log.Debug("ipfs swarm peers") - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -101,7 +101,7 @@ ipfs swarm addrs lists all addresses this node is aware of. }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -164,7 +164,7 @@ ipfs swarm addrs local lists all local addresses the node is listening on. }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -213,7 +213,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3 Run: func(req cmds.Request, res cmds.Response) { ctx := context.TODO() - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -266,7 +266,7 @@ ipfs swarm disconnect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQA cmds.StringArg("address", true, true, "address of peer to connect to").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -386,7 +386,7 @@ Filters default to those specified under the "Swarm.AddrFilters" config key. "rm": swarmFiltersRmCmd, }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -433,7 +433,7 @@ add your filters to the ipfs config file. cmds.StringArg("address", true, true, "multiaddr to filter").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -475,7 +475,7 @@ remove your filters from the ipfs config file. cmds.StringArg("address", true, true, "multiaddr filter to remove").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/tour.go b/core/commands/tour.go index 80075036b..ce702aee6 100644 --- a/core/commands/tour.go +++ b/core/commands/tour.go @@ -37,7 +37,7 @@ IPFS very quickly. To start, run: func tourRunFunc(req cmds.Request, res cmds.Response) { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -78,8 +78,8 @@ var cmdIpfsTourNext = &cmds.Command{ Run: func(req cmds.Request, res cmds.Response) { w := new(bytes.Buffer) - path := req.Context().ConfigRoot - cfg, err := req.Context().GetConfig() + path := req.InvocContext().ConfigRoot + cfg, err := req.InvocContext().GetConfig() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -116,8 +116,8 @@ var cmdIpfsTourRestart = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - path := req.Context().ConfigRoot - cfg, err := req.Context().GetConfig() + path := req.InvocContext().ConfigRoot + cfg, err := req.InvocContext().GetConfig() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -138,7 +138,7 @@ var cmdIpfsTourList = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - cfg, err := req.Context().GetConfig() + cfg, err := req.InvocContext().GetConfig() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/unixfs/ls.go b/core/commands/unixfs/ls.go index 793e839ac..256d87db6 100644 --- a/core/commands/unixfs/ls.go +++ b/core/commands/unixfs/ls.go @@ -52,7 +52,7 @@ size is the IPFS link size. cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from").EnableStdin(), }, Run: func(req cmds.Request, res cmds.Response) { - node, err := req.Context().GetNode() + node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -66,7 +66,7 @@ size is the IPFS link size. } for _, fpath := range paths { - ctx := req.Context().Context + ctx := req.Context() merkleNode, err := core.Resolve(ctx, node, path.Path(fpath)) if err != nil { res.SetError(err, cmds.ErrNormal) diff --git a/core/commands/update.go b/core/commands/update.go index a86619897..9b14c2464 100644 --- a/core/commands/update.go +++ b/core/commands/update.go @@ -33,7 +33,7 @@ var updateCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -73,7 +73,7 @@ var UpdateCheckCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -109,7 +109,7 @@ var UpdateLogCmd = &cmds.Command{ }, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.Context().GetNode() + n, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/test/supernode_client/main.go b/test/supernode_client/main.go index 4e037e53b..d6111a118 100644 --- a/test/supernode_client/main.go +++ b/test/supernode_client/main.go @@ -233,8 +233,6 @@ func toPeerInfo(bootstrap config.BootstrapPeer) (p peer.PeerInfo, err error) { func cmdCtx(node *core.IpfsNode, repoPath string) commands.Context { return commands.Context{ - // TODO deprecate this shit - Context: context.Background(), Online: true, ConfigRoot: repoPath, LoadConfig: func(path string) (*config.Config, error) {