assets.go
func Retrieve(sources []*Source) (http.FileSystem, error) {
	files := make(mfs.Files)

	for i, source := range sources {
		log.Printf("Processing asset source (%d/%d): %s ...", i+1, len(sources), source.Location)

		// Retrieve the file or files
		retFiles, err := retrieve(source.Location)
		if err != nil {
			return nil, &RetrieveError{source.Location, err}
		}

		// If multiple files are returned store them and finish processing.
		// Chekcsum and archive not supported for multiple files.
		if len(retFiles) > 1 {
			for _, file := range retFiles {
				path := strings.TrimSuffix(source.Path, "/") + "/" + file.path
				log.Printf("Created asset: %s ...", path)
				files[path] = &mfs.File{file.data, file.modTime}
			}
			continue
		}

		// Process the single returned file
		file := retFiles[0]

		// Verify the file checksum if requested
		if source.Checksum != nil {
			err = verifyChecksum(source.Checksum, file.data)
			if err != nil {
				return nil, &ChecksumError{source.Location, err}
			}
		}

		// If the file is not an archive store it and finish processing.
		if source.Archive == nil {
			log.Printf("Created asset: %s ...", source.Path)
			files[source.Path] = &mfs.File{file.data, file.modTime}
			continue
		}

		// Extract files from the archive and store them.
		archFiles, err := processArchive(source.Archive, file.data)
		if err != nil {
			return nil, &ArchiveError{source.Location, err}
		}

		for _, file := range archFiles {
			log.Printf("Created asset: %s ...", file.path)
			files[file.path] = &mfs.File{file.data, file.modTime}
		}

	}

	fs, err := mfs.New(files)
	if err != nil {
		return nil, err
	}

	return httpfs.New(fs), nil
}
func Retrieve(sources []*Source) (http.FileSystem, error) {
	files := make(mfs.Files)

	for i, source := range sources {
		log.Printf("Processing asset source (%d/%d): %s ...", i+1, len(sources), source.Location)

		// Retrieve the file or files
		retFiles, err := retrieve(source.Location)
		if err != nil {
			return nil, &RetrieveError{source.Location, err}
		}

		// If multiple files are returned store them and finish processing.
		// Chekcsum and archive not supported for multiple files.
		if len(retFiles) > 1 {
			for _, file := range retFiles {
				path := strings.TrimSuffix(source.Path, "/") + "/" + file.path
				log.Printf("Created asset: %s ...", path)
				files[path] = &mfs.File{file.data, file.modTime}
			}
			continue
		}

		// Process the single returned file
		file := retFiles[0]

		// Verify the file checksum if requested
		if source.Checksum != nil {
			err = verifyChecksum(source.Checksum, file.data)
			if err != nil {
				return nil, &ChecksumError{source.Location, err}
			}
		}

		// If the file is not an archive store it and finish processing.
		if source.Archive == nil {
			log.Printf("Created asset: %s ...", source.Path)
			files[source.Path] = &mfs.File{file.data, file.modTime}
			continue
		}

		// Extract files from the archive and store them.
		archFiles, err := processArchive(source.Archive, file.data)
		if err != nil {
			return nil, &ArchiveError{source.Location, err}
		}

		for _, file := range archFiles {
			log.Printf("Created asset: %s ...", file.path)
			files[file.path] = &mfs.File{file.data, file.modTime}
		}

	}

	fs, err := mfs.New(files)
	if err != nil {
		return nil, err
	}

	return httpfs.New(fs), nil
}
// Retrieve retrieves and processes the specified asset sources, and returns
// them using a http.FileSystem interface.