github.com/sirkon/goproxy@v1.4.8/plugin/vcs/module.go (about)

     1  package vcs
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"time"
     9  
    10  	"github.com/rs/zerolog"
    11  
    12  	"github.com/sirkon/goproxy"
    13  	"github.com/sirkon/goproxy/internal/errors"
    14  	"github.com/sirkon/goproxy/internal/modfetch"
    15  )
    16  
    17  type vcsModule struct {
    18  	repo modfetch.Repo
    19  }
    20  
    21  func (s *vcsModule) ModulePath() string {
    22  	return s.repo.ModulePath()
    23  }
    24  
    25  func (s *vcsModule) Versions(ctx context.Context, prefix string) (tags []string, err error) {
    26  	defer func() {
    27  		if err != nil {
    28  			err = errors.Wrap(err, "vcs getting versions")
    29  		}
    30  	}()
    31  	type data struct {
    32  		tags []string
    33  		err  error
    34  	}
    35  	dataChan := make(chan data, 1)
    36  	go func() {
    37  		t, e := s.repo.Versions(prefix)
    38  		if len(t) == 0 {
    39  			info, err := s.repo.Latest()
    40  			if err != nil {
    41  				e = err
    42  			} else {
    43  				t = []string{info.Version}
    44  			}
    45  		}
    46  		dataChan <- data{
    47  			tags: t,
    48  			err:  e,
    49  		}
    50  	}()
    51  
    52  	select {
    53  	case info := <-dataChan:
    54  		return info.tags, info.err
    55  	case <-ctx.Done():
    56  		return nil, ctx.Err()
    57  	}
    58  }
    59  
    60  func (s *vcsModule) Stat(ctx context.Context, rev string) (res *goproxy.RevInfo, err error) {
    61  	defer func() {
    62  		if err != nil {
    63  			err = errors.Wrap(err, "vcs getting stat")
    64  		}
    65  	}()
    66  
    67  	type data struct {
    68  		info *goproxy.RevInfo
    69  		err  error
    70  	}
    71  	dataChan := make(chan data, 1)
    72  	go func() {
    73  		raw, err := s.repo.Stat(rev)
    74  		if err != nil {
    75  			dataChan <- data{
    76  				info: nil,
    77  				err:  err,
    78  			}
    79  			return
    80  		}
    81  		res := &goproxy.RevInfo{}
    82  		res.Name = raw.Name
    83  		res.Short = raw.Short
    84  		res.Time = raw.Time.Format(time.RFC3339)
    85  		res.Version = raw.Version
    86  		dataChan <- data{
    87  			info: res,
    88  			err:  nil,
    89  		}
    90  	}()
    91  
    92  	select {
    93  	case res := <-dataChan:
    94  		return res.info, res.err
    95  	case <-ctx.Done():
    96  		return nil, ctx.Err()
    97  	}
    98  }
    99  
   100  func (s *vcsModule) GoMod(ctx context.Context, version string) (file []byte, err error) {
   101  	defer func() {
   102  		if err != nil {
   103  			err = errors.Wrap(err, "vcs getting go.mod")
   104  		}
   105  	}()
   106  
   107  	type data struct {
   108  		data []byte
   109  		err  error
   110  	}
   111  	dataChan := make(chan data, 1)
   112  	go func() {
   113  		res, err := s.repo.GoMod(version)
   114  		dataChan <- data{
   115  			data: res,
   116  			err:  err,
   117  		}
   118  	}()
   119  
   120  	select {
   121  	case res := <-dataChan:
   122  		return res.data, res.err
   123  	case <-ctx.Done():
   124  		return nil, ctx.Err()
   125  	}
   126  }
   127  
   128  func (s *vcsModule) Zip(ctx context.Context, version string) (file io.ReadCloser, err error) {
   129  	type data struct {
   130  		file io.ReadCloser
   131  		err  error
   132  	}
   133  	dataChan := make(chan data, 1)
   134  
   135  	go func() {
   136  		dir, err := ioutil.TempDir(".", ".downloads")
   137  		if err != nil {
   138  			dataChan <- data{
   139  				file: nil,
   140  				err:  errors.Wrap(err, "vcs creating temporary directory to save source archive"),
   141  			}
   142  		}
   143  		defer func() {
   144  			if err := os.RemoveAll(dir); err != nil {
   145  				zerolog.Ctx(ctx).Error().Err(err).Msg("failed to remove temporary directory")
   146  			}
   147  		}()
   148  		fileName, err := s.repo.Zip(version, dir)
   149  		if err != nil {
   150  			dataChan <- data{
   151  				file: nil,
   152  				err:  errors.Wrap(err, "vcs getting source archive"),
   153  			}
   154  			return
   155  		}
   156  
   157  		osFile, err := os.Open(fileName)
   158  		if err != nil {
   159  			dataChan <- data{
   160  				file: nil,
   161  				err:  errors.Wrap(err, "vcs opening downloaded source archive"),
   162  			}
   163  			return
   164  		}
   165  
   166  		dataChan <- data{
   167  			file: osFile,
   168  			err:  nil,
   169  		}
   170  	}()
   171  
   172  	select {
   173  	case res := <-dataChan:
   174  		return res.file, res.err
   175  	case <-ctx.Done():
   176  		return nil, errors.Wrap(ctx.Err(), "vcs getting source archive")
   177  	}
   178  }