func (b *Bag) GetManifest(manifestType, algorithm string) (*Manifest) {
	for _, m := range b.Manifests {
		if m.Type() == manifestType && m.Algorithm() == algorithm {
			return m
		}
	}
	return nil
}
Returns the manifest with the specified algorithm and type,
or nil. For example, GetManifest(PayloadManifest, "sha256")
returns either a reference to manifest-sha256.txt or nil.
GetManifest(TagManifest, "md5") returns a reference to
tagmanifest-md5.txt or nil.
package bagins
import (
	"github.com/APTrust/bagins/bagutil"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
)
type Bag struct {
	pathToFile              string  
	payload                 *Payload
	Manifests               []*Manifest
	tagfiles                map[string]*TagFile  
	excludeFromTagManifests map[string]bool
}
func NewBag(location string, name string, hashNames []string, createTagManifests bool) (*Bag, error) {
	bag := new(Bag)
	if bag.Manifests == nil {
		bag.Manifests = make([]*Manifest, 0)
	}
	bag.pathToFile = filepath.Join(location, name)
	err := os.Mkdir(bag.pathToFile, 0755)
	if err != nil {
		return nil, err
	}
	for _, hashName := range hashNames {
		lcHashName := strings.ToLower(hashName)
		manifest, err := NewManifest(bag.Path(), lcHashName, PayloadManifest)
		if err != nil {
			return nil, err
		}
		bag.Manifests = append(bag.Manifests, manifest)
		if createTagManifests == true {
			tagManifestName := fmt.Sprintf("tagmanifest-%s.txt", lcHashName)
			fullPath := filepath.Join(bag.Path(), tagManifestName)
			tagmanifest, err := NewManifest(fullPath, lcHashName, TagManifest)
			if err != nil {
				return nil, err
			}
			bag.Manifests = append(bag.Manifests, tagmanifest)
		}
	}
	plPath := filepath.Join(bag.Path(), "data")
	err = os.Mkdir(plPath, 0755)
	if err != nil {
		return nil, err
	}
	bag.payload, err = NewPayload(plPath)
	if err != nil {
		return nil, err
	}
	bag.tagfiles = make(map[string]*TagFile)
	bag.excludeFromTagManifests = make(map[string]bool)
	tf, err := bag.createBagItFile()
	if err != nil {
		return nil, err
	}
	bag.tagfiles["bagit.txt"] = tf
	errors := bag.Save()
	if err != nil && len(errors) > 0 {
		message := ""
		for _, e := range errors {
			message = fmt.Sprintf("%s, %s", message, e.Error())
		}
		return nil, fmt.Errorf(message)
	}
	return bag, nil
}
func (b *Bag) createBagItFile() (*TagFile, error) {
	if err := b.AddTagfile("bagit.txt"); err != nil {
		return nil, err
	}
	bagit, err := b.TagFile("bagit.txt")
	if err != nil {
		return nil, err
	}
	bagit.Data.AddField(*NewTagField("BagIt-Version", "0.97"))
	bagit.Data.AddField(*NewTagField("Tag-File-Character-Encoding", "UTF-8"))
	return bagit, nil
}
func ReadBag(pathToFile string, tagfiles []string) (*Bag, error) {
	fi, err := os.Stat(pathToFile)
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, fmt.Errorf("%s is not a directory.", pathToFile)
	}
	payload, err := NewPayload(filepath.Join(pathToFile, "data"))
	if err != nil {
		return nil, err
	}
	bag := new(Bag)
	bag.pathToFile = pathToFile
	bag.payload = payload
	bag.tagfiles = make(map[string]*TagFile)
	bag.excludeFromTagManifests = make(map[string]bool)
	errors := bag.findManifests()
	if errors != nil {
		errorMessage := ""
		for _, e := range errors {
			errorMessage = fmt.Sprintf("%s; %s", errorMessage, e.Error())
		}
		return nil, fmt.Errorf(errorMessage)
	}
	if len(bag.Manifests) == 0 {
		return nil, fmt.Errorf("Unable to parse a manifest")
	}
	for i := range bag.Manifests {
		manifest := bag.Manifests[i]
		manifestPath := manifest.Name()
		if filepath.Dir(manifestPath) != bag.pathToFile {
			manifestPath = filepath.Join(bag.pathToFile, manifest.Name())
		}
		if _, err := os.Stat(manifestPath); err != nil {
			return nil, fmt.Errorf("Can't find manifest: %v", err)
		}
		parsedManifest, errs := ReadManifest(manifestPath)
		if errs != nil && len(errs) > 0 {
			errors := ""
			for _, e := range(errs) {
				errors = fmt.Sprintf("%s; %s", errors, e.Error())
			}
			return nil, fmt.Errorf("Unable to parse manifest %s: %s", manifestPath, errors)
		} else {
			bag.Manifests[i] = parsedManifest
		}
	}
	for _, tName := range tagfiles {
		tf, errs := ReadTagFile(filepath.Join(bag.pathToFile, tName))
		if len(errs) != 0 && strings.Index(os.Args[0], "bagmaker") > -1 {
			log.Println("While parsing tagfiles:", errs)
		}
		if tf != nil {
			bag.tagfiles[tName] = tf
		}
	}
	return bag, nil
}
func (b *Bag) findManifests() ([]error){
	if b.Manifests == nil {
		b.Manifests = make([]*Manifest, 0)
	}
	if len(b.Manifests) == 0 {
		bagFiles, _ := b.ListFiles()
		for _, fName := range bagFiles {
			filePath := filepath.Join(b.pathToFile, fName)
			payloadManifestPrefix := filepath.Join(b.pathToFile, "manifest-")
			tagManifestPrefix := filepath.Join(b.pathToFile, "tagmanifest-")
			if strings.HasPrefix(filePath, payloadManifestPrefix) ||
				strings.HasPrefix(filePath, tagManifestPrefix) {
				manifest, errors := ReadManifest(filePath)
				if errors != nil && len(errors) > 0 {
					return errors
				}
				b.Manifests = append(b.Manifests, manifest)
			}
		}
	}
	return nil
}
func (b *Bag) AddFile(src string, dst string) error {
	payloadManifests := b.GetManifests(PayloadManifest)
	_, err := b.payload.Add(src, dst, payloadManifests)
	if err != nil {
		return err
	}
	return err
}
func (b *Bag) AddDir(src string) (errs []error) {
	payloadManifests := b.GetManifests(PayloadManifest)
	_, errs = b.payload.AddAll(src, payloadManifests)
	return errs
}
func (b *Bag) AddTagfile(name string) error {
	tagFilePath := filepath.Join(b.Path(), name)
	if err := os.MkdirAll(filepath.Dir(tagFilePath), 0766); err != nil {
		return err
	}
	tf, err := NewTagFile(tagFilePath)
	if err != nil {
		return err
	}
	b.tagfiles[name] = tf
	if err := tf.Create(); err != nil {
		return err
	}
	return nil
}
func (b *Bag) AddCustomTagfile(sourcePath string, destPath string, includeInTagManifests bool) error {
	if (strings.HasPrefix(destPath, "/data") ||
		strings.HasPrefix(destPath, "/") || strings.Contains(destPath, "..")) {
		return fmt.Errorf("Illegal value '%s' for param destPath. " +
			"File name cannot start with '/' or '/data' or contain '..'", destPath)
	}
	absSourcePath, err := filepath.Abs(sourcePath)
	if err != nil {
		return err
	}
	absDestPath, err := filepath.Abs(filepath.Join(b.pathToFile, destPath))
	if err != nil {
		return err
	}
	if absSourcePath != absDestPath {
		sourceFile, err := os.Open(absSourcePath)
		if err != nil {
			return err
		}
		defer sourceFile.Close()
		if err = os.MkdirAll(filepath.Dir(absDestPath), 0766); err != nil {
			return err
		}
		destFile, err := os.Create(absDestPath)
		if err != nil {
			return err
		}
		defer destFile.Close()
		_, err = io.Copy(destFile, sourceFile)
		if err != nil {
			return err
		}
	}
	if includeInTagManifests == false {
		if b.excludeFromTagManifests == nil {
			b.excludeFromTagManifests = make(map[string]bool)
		}
		b.excludeFromTagManifests[destPath] = true
	}
	return nil
}
func (b *Bag) TagFile(name string) (*TagFile, error) {
	if tf, ok := b.tagfiles[name]; ok {
		return tf, nil
	}
	return nil, fmt.Errorf("Unable to find tagfile %s", name)
}
func (b *Bag) ListTagFiles() []string {
	names := make([]string, len(b.tagfiles))
	i := 0
	for k, _ := range b.tagfiles {
		names[i] = k
		i++
	}
	return names
}
func (b *Bag) UnparsedTagFiles() ([]string, error) {
	var files []string
	visit := func(pathToFile string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		relativePath, err := filepath.Rel(b.Path(), pathToFile)
		if err != nil {
			return err
		}
		isPayload := strings.HasPrefix(pathToFile, b.payload.Name())
		isManifest := (strings.HasPrefix(relativePath, "tagmanifest-") ||
			strings.HasPrefix(relativePath, "manifest-"))
		_, isParsedTagFile := b.tagfiles[relativePath]
		if !info.IsDir() && !isPayload && !isParsedTagFile && !isManifest {
			if relativePath != "." {
				files = append(files, relativePath)
			}
		}
		return err
	}
	if err := filepath.Walk(b.Path(), visit); err != nil {
		return nil, err
	}
	return files, nil
}
func (b *Bag) BagInfo() (*TagFile, error) {
	tf, err := b.TagFile("bag-info.txt")
	if err != nil {
		return nil, err
	}
	return tf, nil
}