github.com/ssube/gitlab-ci-multi-runner@v1.2.1-0.20160607142738-b8d1285632e6/commands/helpers/cache_extractor.go (about)

     1  package helpers
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"os"
     9  	"path/filepath"
    10  	"time"
    11  
    12  	"github.com/Sirupsen/logrus"
    13  	"github.com/codegangsta/cli"
    14  
    15  	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/common"
    16  	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers/archives"
    17  	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers/formatter"
    18  )
    19  
    20  type CacheExtractorCommand struct {
    21  	retryHelper
    22  	File string `long:"file" description:"The file containing your cache artifacts"`
    23  	URL  string `long:"url" description:"Download artifacts instead of uploading them"`
    24  }
    25  
    26  func (c *CacheExtractorCommand) download() (bool, error) {
    27  	os.MkdirAll(filepath.Dir(c.File), 0600)
    28  
    29  	file, err := ioutil.TempFile(filepath.Dir(c.File), "cache")
    30  	if err != nil {
    31  		return false, err
    32  	}
    33  	defer file.Close()
    34  	defer os.Remove(file.Name())
    35  
    36  	resp, err := http.Get(c.URL)
    37  	if err != nil {
    38  		return true, err
    39  	}
    40  	defer resp.Body.Close()
    41  
    42  	if resp.StatusCode == 404 {
    43  		return false, os.ErrNotExist
    44  	} else if resp.StatusCode/100 != 2 {
    45  		// Retry on server errors
    46  		retry := resp.StatusCode/100 == 5
    47  		return retry, fmt.Errorf("Received: %s", resp.Status)
    48  	}
    49  
    50  	fi, _ := os.Lstat(c.File)
    51  	date, _ := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
    52  	if fi != nil && !date.After(fi.ModTime()) {
    53  		logrus.Infoln(filepath.Base(c.File), "is up to date")
    54  		return false, nil
    55  	}
    56  
    57  	logrus.Infoln("Downloading", filepath.Base(c.File))
    58  	_, err = io.Copy(file, resp.Body)
    59  	if err != nil {
    60  		return true, err
    61  	}
    62  	os.Chtimes(file.Name(), time.Now(), date)
    63  
    64  	err = os.Rename(file.Name(), c.File)
    65  	if err != nil {
    66  		return false, err
    67  	}
    68  	return false, nil
    69  }
    70  
    71  func (c *CacheExtractorCommand) Execute(context *cli.Context) {
    72  	formatter.SetRunnerFormatter()
    73  
    74  	if len(c.File) == 0 {
    75  		logrus.Fatalln("Missing cache file")
    76  	}
    77  
    78  	if c.URL != "" {
    79  		err := c.doRetry(c.download)
    80  		if err != nil && !os.IsNotExist(err) {
    81  			logrus.Warningln(err)
    82  		}
    83  	}
    84  
    85  	err := archives.ExtractZipFile(c.File)
    86  	if err != nil && !os.IsNotExist(err) {
    87  		logrus.Fatalln(err)
    88  	}
    89  }
    90  
    91  func init() {
    92  	common.RegisterCommand2("cache-extractor", "download and extract cache artifacts (internal)", &CacheExtractorCommand{
    93  		retryHelper: retryHelper{
    94  			Retry:     2,
    95  			RetryTime: time.Second,
    96  		},
    97  	})
    98  }