kubesphere.io/s2irun@v3.2.1+incompatible/pkg/scm/downloaders/binary/download.go (about)

     1  package binary
     2  
     3  import (
     4  	"github.com/kubesphere/s2irun/pkg/api"
     5  	"github.com/kubesphere/s2irun/pkg/api/constants"
     6  	"github.com/kubesphere/s2irun/pkg/scm/git"
     7  	"github.com/kubesphere/s2irun/pkg/utils/bytefmt"
     8  	"github.com/kubesphere/s2irun/pkg/utils/fs"
     9  	utilglog "github.com/kubesphere/s2irun/pkg/utils/glog"
    10  	"io"
    11  	"net/http"
    12  	"path/filepath"
    13  	"strconv"
    14  	"strings"
    15  )
    16  
    17  var glog = utilglog.StderrLog
    18  
    19  // File represents a simplest possible Downloader implementation where the
    20  // sources are just copied from local directory.
    21  type File struct {
    22  	fs.FileSystem
    23  }
    24  
    25  // Download download sources from a http link into the working directory.
    26  // Caller guarantees that config.Source.IsLocal() is true.
    27  func (f *File) Download(config *api.Config) (*git.SourceInfo, error) {
    28  	_, filename := filepath.Split(config.Source.String())
    29  	config.WorkingSourceDir = filepath.Join(config.WorkingDir, constants.Source)
    30  	binaryPath := filepath.Join(config.WorkingSourceDir, filename)
    31  	glog.V(0).Infof("Start Download Binary %s", filename)
    32  	resp, err := http.Get(config.Source.String())
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	defer resp.Body.Close()
    37  	out, err := f.Create(binaryPath)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	defer out.Close()
    43  
    44  	strsize := resp.Header.Get("Content-Length")
    45  	size, _ := strconv.ParseUint(strsize, 10, 64)
    46  
    47  	counter := &WriteCounter{Size: size}
    48  	_, err = io.Copy(out, io.TeeReader(resp.Body, counter))
    49  	glog.V(0).Infof("Finish Download Binary %s", filename)
    50  	glog.V(0).Infof("Binary size %s", bytefmt.ByteSize(counter.Total))
    51  	return &git.SourceInfo{
    52  		Location:   config.Source.String(),
    53  		ContextDir: config.ContextDir,
    54  		BinaryName: filename,
    55  		BinarySize: counter.Total,
    56  	}, nil
    57  }
    58  
    59  // write cycle.
    60  type WriteCounter struct {
    61  	Total uint64
    62  	Size  uint64
    63  }
    64  
    65  func (wc *WriteCounter) Write(p []byte) (int, error) {
    66  	n := len(p)
    67  	wc.Total += uint64(n)
    68  	wc.PrintProgress()
    69  	return n, nil
    70  }
    71  
    72  func (wc WriteCounter) PrintProgress() {
    73  	// Clear the line by using a character return to go back to the start and remove
    74  	// the remaining characters by filling it with spaces
    75  	glog.V(0).Infof("\r%s", strings.Repeat(" ", 35))
    76  
    77  	// Return again and print current status of download
    78  	// We use the humanize package to print the bytes in a meaningful way (e.g. 10 MB)
    79  	if wc.Size > 0 {
    80  		glog.V(0).Infof("\rDownloading... %s/%s", bytefmt.ByteSize(wc.Total), bytefmt.ByteSize(wc.Size))
    81  	} else {
    82  		glog.V(0).Infof("\rDownloading... %s complete", bytefmt.ByteSize(wc.Total))
    83  	}
    84  
    85  }