func ArchiveManifest(a Archiver, manifest Manifest) error {
	types.SubmitMetricCount("archive_manifest", float32(len(manifest.entries)), map[string]string{"root": manifest.srcRoot})
	for _, entry := range manifest.entries {
		absSrcPath := filepath.Join(manifest.srcRoot, entry.src)
		relDstPath := entry.dst
		err := a.archiveOne(absSrcPath, relDstPath)
		if err != nil {
			types.SubmitMetricCount("archive_one.fail", 1, map[string]string{"srcRoot": manifest.srcRoot})
			log.Print(err)
			raven.CaptureError(err, map[string]string{
				"dst":     entry.dst,
				"src":     entry.src,
				"srcRoot": manifest.srcRoot,
			})
			continue
		}
		types.SubmitMetricCount("archive_one.success", 1, map[string]string{"srcRoot": manifest.srcRoot})
	}
	return nil
}
ArchiveManifest uses an `archiver` to archive a `manifest` once.
package server
import (
	"io"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"time"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3iface"
	raven "github.com/getsentry/raven-go"
	"github.com/richo/roving/types"
)
var getTimestamp func() int64
func init() {
	getTimestamp = func() int64 {
		return time.Now().Unix()
	}
}
func ArchiveToTimestampedDirsForever(archiver Archiver, absSrcPath string, interval time.Duration) {
	ticker := time.NewTicker(interval)
	for {
		select {
		case <-ticker.C:
			log.Printf("Archiving to timestamped dir src=%s dst=%s", absSrcPath, archiver.DescribeDstRoot())
			err := archiveToTimestampedDir(archiver, absSrcPath)
			if err != nil {
				raven.CaptureErrorAndWait(err, nil)
				log.Print(err)
			}
		}
	}
}
func ArchiveToNamedDir(a Archiver, absSrcPath, dstSubRoot string) error {
	manifest := newSimpleManifest(absSrcPath, dstSubRoot)
	return ArchiveManifest(a, manifest)
}