github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/lib/resolve.go (about)

     1  package lib
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/qri-io/qri/dsref"
     8  	"github.com/qri-io/qri/remote"
     9  )
    10  
    11  // ParseAndResolveRef combines reference parsing and resolution
    12  func (inst *Instance) ParseAndResolveRef(ctx context.Context, refStr, source string) (dsref.Ref, string, error) {
    13  	log.Debugf("inst.ParseAndResolveRef refStr=%q source=%q", refStr, source)
    14  	ref, err := dsref.Parse(refStr)
    15  	if err != nil {
    16  		return ref, "", fmt.Errorf("%q is not a valid dataset reference: %w", refStr, err)
    17  	}
    18  
    19  	// Resolve the reference
    20  	location, err := inst.ResolveReference(ctx, &ref, source)
    21  	if err != nil {
    22  		return ref, location, err
    23  	}
    24  	return ref, location, err
    25  }
    26  
    27  // ResolveReference finds the identifier & HEAD path for a dataset reference.
    28  // the source parameter determines which subsystems of Qri to use when resolving
    29  func (inst *Instance) ResolveReference(ctx context.Context, ref *dsref.Ref, source string) (string, error) {
    30  	log.Debugf("inst.ResolveReference ref=%q source=%q", ref, source)
    31  	if inst == nil {
    32  		return "", dsref.ErrRefNotFound
    33  	}
    34  
    35  	// Handle the "me" convenience shortcut
    36  	if ref.Username == "me" {
    37  		ref.Username = inst.cfg.Profile.Peername
    38  	}
    39  
    40  	resolver, err := inst.resolverForSource(source)
    41  	if err != nil {
    42  		log.Debug("inst.resolverForSource error=%q", err)
    43  		return "", err
    44  	}
    45  
    46  	return resolver.ResolveRef(ctx, ref)
    47  }
    48  
    49  func (inst *Instance) resolverForSource(source string) (dsref.Resolver, error) {
    50  	switch source {
    51  	case "":
    52  		return inst.defaultResolver(), nil
    53  	case "local":
    54  		return dsref.SequentialResolver(
    55  			inst.dscache,
    56  			inst.repo,
    57  		), nil
    58  	case "network":
    59  		return dsref.ParallelResolver(
    60  			inst.registryResolver(),
    61  			inst.p2pResolver(),
    62  		), nil
    63  	case "registry":
    64  		return inst.registryResolver(), nil
    65  	case "p2p":
    66  		return inst.p2pResolver(), nil
    67  	}
    68  
    69  	// TODO (b5) - source could be one of:
    70  	// * configured remote name
    71  	// * peername
    72  	// * peer multiaddress
    73  	// add support for peername & multiaddress resolution
    74  	addr, err := remote.Address(inst.GetConfig(), source)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	return inst.remoteClient.NewRemoteRefResolver(addr), nil
    79  }
    80  
    81  func (inst *Instance) defaultResolver() dsref.Resolver {
    82  	return dsref.SequentialResolver(
    83  		inst.dscache,
    84  		inst.repo,
    85  		dsref.ParallelResolver(
    86  			inst.registryResolver(),
    87  			// inst.node,
    88  		),
    89  	)
    90  }
    91  
    92  func (inst *Instance) registryResolver() dsref.Resolver {
    93  	var location string
    94  	if inst.cfg.Registry != nil {
    95  		location = inst.cfg.Registry.Location
    96  	}
    97  	return inst.remoteClient.NewRemoteRefResolver(location)
    98  }
    99  
   100  func (inst *Instance) p2pResolver() dsref.Resolver {
   101  	return inst.node.NewP2PRefResolver()
   102  }