Example #1
0
func (input *runnerTarInput) Persist() error {
	f, err := input.factory.inputData.Open()
	if err != nil {
		return err
	}
	hasher := common.NewHashReader(f, sha1.New())
	streamHash := fmt.Sprintf("%0x", hasher.Sum(nil))
	uncompressedSize := hasher.Length()
	f.Close()

	f, err = input.factory.inputData.Open()
	if err != nil {
		return err
	}
	defer f.Close()

	return input.persistFromTarStream(
		f,
		"",
		uncompressedSize,
		streamHash,
	)
}
Example #2
0
func (input *runnerBaseInput) persistFromTarStream(
	r io.Reader,
	compressionFormat string,
	uncompressedSize int64,
	streamHash string,
) error {
	tmpPath := fmt.Sprintf("%s.tmp", input.path)
	if err := os.MkdirAll(tmpPath, 0755); err != nil {
		return err
	}
	defer os.RemoveAll(tmpPath)

	input.Reserve(uncompressedSize)

	hasher := common.NewHashReader(r, sha1.New())
	var uncompressedReader io.Reader

	if compressionFormat == "gzip" {
		gz, err := gzip.NewReader(hasher)
		if err != nil {
			return err
		}
		defer gz.Close()
		uncompressedReader = gz
	} else if compressionFormat == "bzip2" {
		uncompressedReader = bzip2.NewReader(hasher)
	} else {
		uncompressedReader = hasher
	}

	archive := tar.NewReader(uncompressedReader)

	sha1sumFile, err := os.Create(fmt.Sprintf("%s.sha1", input.path))
	if err != nil {
		return err
	}
	defer sha1sumFile.Close()

	var size int64 = 0

	for {
		hdr, err := archive.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		filePath := path.Join(tmpPath, hdr.Name)
		if hdr.FileInfo().IsDir() {
			if err := os.MkdirAll(filePath, 0755); err != nil {
				return err
			}
		} else {
			if err := os.MkdirAll(path.Dir(filePath), 0755); err != nil {
				return err
			}
			fd, err := os.Create(filePath)
			if err != nil {
				return err
			}
			defer fd.Close()

			innerHasher := common.NewHashReader(archive, sha1.New())
			if _, err := io.Copy(fd, innerHasher); err != nil {
				return err
			}
			_, err = fmt.Fprintf(
				sha1sumFile,
				"%0x *%s/%s\n",
				innerHasher.Sum(nil),
				input.Hash()[2:],
				hdr.Name,
			)
			if err != nil {
				return err
			}
			size += hdr.Size
		}
	}

	if streamHash != fmt.Sprintf("%0x", hasher.Sum(nil)) {
		return errors.New(fmt.Sprintf(
			"hash mismatch: expected %s got %s",
			streamHash,
			fmt.Sprintf("%0x", hasher.Sum(nil)),
		))
	}

	settingsFd, err := os.Open(path.Join(tmpPath, "settings.json"))
	if err != nil {
		return err
	}
	defer settingsFd.Close()
	decoder := json.NewDecoder(settingsFd)
	if err := decoder.Decode(input.Settings()); err != nil {
		return err
	}

	if err := os.Rename(tmpPath, input.path); err != nil {
		return err
	}

	input.Commit(size)

	return nil
}