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

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/qri-io/ioes"
     8  	"github.com/qri-io/qri/lib"
     9  	reporef "github.com/qri-io/qri/repo/ref"
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  // NewPullCommand creates an add command
    14  func NewPullCommand(f Factory, ioStreams ioes.IOStreams) *cobra.Command {
    15  	o := &PullOptions{IOStreams: ioStreams}
    16  	cmd := &cobra.Command{
    17  		Use:     "pull DATASET [DATASET...]",
    18  		Aliases: []string{"add"},
    19  		Short:   "fetch & store datasets from other peers",
    20  		Long: `Pull downloads datasets and stores them locally, fetching the dataset log and
    21  dataset version(s). By default pull fetches the latest version of a dataset.
    22  `,
    23  		Example: `  # download a dataset log and latest version
    24    $ qri pull b5/world_bank_population
    25  
    26    # pull a specific version from a remote by hash
    27    $ qri pull ramfox b5/world_bank_population@/ipfs/QmFoo...`,
    28  		Annotations: map[string]string{
    29  			"group": "network",
    30  		},
    31  		RunE: func(cmd *cobra.Command, args []string) error {
    32  			if err := o.Complete(f); err != nil {
    33  				return err
    34  			}
    35  			return o.Run(args)
    36  		},
    37  	}
    38  
    39  	cmd.Flags().StringVar(&o.LinkDir, "link", "", "path to directory to link dataset to")
    40  	cmd.Flags().StringVar(&o.Source, "source", "", "location to pull from")
    41  	cmd.MarkFlagFilename("link")
    42  	cmd.Flags().BoolVar(&o.LogsOnly, "logs-only", false, "only fetch logs, skipping HEAD data")
    43  
    44  	return cmd
    45  }
    46  
    47  // PullOptions encapsulates state for the add command
    48  type PullOptions struct {
    49  	ioes.IOStreams
    50  	LinkDir  string
    51  	Source   string
    52  	LogsOnly bool
    53  
    54  	inst *lib.Instance
    55  }
    56  
    57  // Complete adds any missing configuration that can only be added just before calling Run
    58  func (o *PullOptions) Complete(f Factory) (err error) {
    59  	o.inst, err = f.Instance()
    60  	return
    61  }
    62  
    63  // Run adds another peer's dataset to this user's repo
    64  func (o *PullOptions) Run(args []string) error {
    65  
    66  	if len(args) == 0 {
    67  		return fmt.Errorf("nothing to pull")
    68  	}
    69  	if len(args) > 1 && o.LinkDir != "" {
    70  		return fmt.Errorf("link flag can only be used with a single reference")
    71  	}
    72  
    73  	ctx := context.TODO()
    74  
    75  	for _, arg := range args {
    76  		p := &lib.PullParams{
    77  			Ref:      arg,
    78  			LogsOnly: o.LogsOnly,
    79  		}
    80  
    81  		res, err := o.inst.WithSource(o.Source).Dataset().Pull(ctx, p)
    82  		if err != nil {
    83  			return err
    84  		}
    85  
    86  		asRef := reporef.DatasetRef{
    87  			Peername: res.Peername,
    88  			Name:     res.Name,
    89  			Path:     res.Path,
    90  			Dataset:  res,
    91  		}
    92  
    93  		refStr := refStringer(asRef)
    94  		fmt.Fprintf(o.Out, "\n%s", refStr.String())
    95  	}
    96  
    97  	return nil
    98  }