func pickT(contents []byte) (Migration, error) {
	s := string(contents)
	switch {
	case collection.MatchString(s):
		return new(Collection), nil
	case database.MatchString(s):
		return new(Database), nil
	case graph.MatchString(s):
		return new(Graph), nil
	case aql.MatchString(s):
		return new(AQL), nil
	case fulltextidx.MatchString(s):
		return new(FullTextIndex), nil
	case geoidx.MatchString(s):
		return new(GeoIndex), nil
	case hashidx.MatchString(s):
		return new(HashIndex), nil
	case persistentidx.MatchString(s):
		return new(PersistentIndex), nil
	case skipidx.MatchString(s):
		return new(SkiplistIndex), nil
	case view.MatchString(s):
		return new(SearchView), nil
	default:
		return nil, errors.New("Can't determine YAML type")
	}
}
Reads the migration contents to pick the proper type.
package arangomigo
import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	driver "github.com/arangodb/go-driver"
	"gopkg.in/yaml.v2"
)
type Operation struct {
	checksum string
	fileName string
	Type     string
	Name     string
	Action   Action
}
type Action string
const (
	CREATE Action = "create"
	DELETE Action = "delete"
	MODIFY Action = "modify"
	RUN    Action = "run"
)
var collection = regexp.MustCompile(`^type:\scollection`)
var database = regexp.MustCompile(`^type:\sdatabase`)
var graph = regexp.MustCompile(`^type:\sgraph`)
var aql = regexp.MustCompile(`^type:\saql`)
var fulltextidx = regexp.MustCompile(`^type:\sfulltextindex`)
var geoidx = regexp.MustCompile(`^type:\sgeoindex`)
var hashidx = regexp.MustCompile(`^type:\shashindex`)
var persistentidx = regexp.MustCompile(`^type:\spersistentindex`)
var skipidx = regexp.MustCompile(`^type:\sskiplistindex`)
var view = regexp.MustCompile(`^type:\sview`)
type User struct {
	Username string
	Password string
}
type Database struct {
	Operation `yaml:",inline"`
	Allowed    []User
	Disallowed []string
	cl driver.Client
	db driver.Database
}
type Collection struct {
	Operation `yaml:",inline"`
	ShardKeys      *[]string
	JournalSize    *int
	NumberOfShards *int
	WaitForSync    *bool
	AllowUserKeys  *bool
	Volatile       *bool
	Compactable    *bool
	CollectionType string
}
type FullTextIndex struct {
	Operation  `yaml:",inline"`
	Fields     []string
	Collection string
	MinLength  int
}
type GeoIndex struct {
	Operation  `yaml:",inline"`
	Fields     []string
	Collection string
	GeoJSON    bool
}
type HashIndex struct {
	Operation     `yaml:",inline"`
	Fields        []string
	Collection    string
	Unique        bool
	Sparse        bool
	NoDeduplicate bool
}
type PersistentIndex struct {
	Operation  `yaml:",inline"`
	Fields     []string
	Collection string
	Unique     bool
	Sparse     bool
}
type SkiplistIndex struct {
	Operation     `yaml:",inline"`
	Fields        []string
	Collection    string
	Unique        bool
	Sparse        bool
	NoDeduplicate bool
}
type AQL struct {
	Operation `yaml:",inline"`
	Query     string
	BindVars  map[string]interface{}
}
type EdgeDefinition struct {
	Collection string `json:"collection"`
	To []string `json:"to"`
	From []string `json:"from"`
}
type Graph struct {
	Operation `yaml:",inline"`
	Smart *bool
	SmartGraphAttribute string
	Shards int
	OrphanVertices []string
	EdgeDefinitions []EdgeDefinition
	RemoveEdges []string
	RemoveVertices []string
}
type PairedMigrations struct {
	change Migration
	undo   Migration
}
type SearchView struct {
	Operation `yaml:",inline"`
	CleanupIntervalStep *int64 `yaml:"cleanupIntervalStep,omitempty"`
	CommitIntervalMsec *int64 `yaml:"commitIntervalMsec,omitempty"`
	ConsolidationIntervalMsec *int64 `yaml:"consolidationIntervalMsec,omitempty"`
	ConsolidationPolicy *ConsolidationPolicy `yaml:"consolidationPolicy,omitempty"`
	SortFields []SortField `yaml:"primarySort,omitempty"`
	Links []SearchElementProperties `yaml:"links,omitempty"`
}
type ConsolidationPolicy struct {
	Type string
	Options map[string]interface{}
}
type SortField struct {
	Field string
	Ascending *bool `yaml:"ascending,omitempty"`
}
type SearchElementProperties struct {
	Name string
	Analyzers []string `yaml:"analyzers,omitempty"`
	Fields []SearchElementProperties `yaml:"fields,omitempty"`
	IncludeAllFields *bool `yaml:"includeAllFields,omitempty"`
	StoreValues *string `yaml:"storeValues,omitempty"`
	TrackListPositions *bool `yaml:"trackListPositions,omitempty"`
}
var validVersion = regexp.MustCompile(`^\d*(\.\d*)*?$`)
func migrations(paths []string) ([]PairedMigrations, error) {
	var pms []PairedMigrations
	for _, path := range paths {
		ms, err := loadFrom(path)
		if err != nil {
			return nil, err
		}
		if len(ms) == 0 {
			return nil, errors.New("Could not find migrations at path '" + path + "'")
		}
		for _, m := range ms {
			pm := PairedMigrations{change: m, undo: nil}
			pms = append(pms, pm)
		}
	}
	return pms, nil
}
func lpadToLength(s string, l int) string {
	dest := make([]rune, l)
	copy(dest[l-len(s):], []rune(s))
	return string(dest)
}
func version(s string) string {
	s = filepath.Base(s)
	idx := strings.IndexRune(s, '_')
	if idx == -1 {
		idx = strings.Index(s, ".migration")
	}
	out := s[:idx]
	if !validVersion.MatchString(out) {
		panic(fmt.Sprintf("File name doesn't match pattern: '%s'", s))
	}
	return out
}
func nearlyLexical(s []string) func(i, j int) bool {
	return func(i, j int) bool {
		curV := version(s[i])
		toV := version(s[j])
		curVS := strings.Split(curV, ".")
		toVS := strings.Split(toV, ".")
		cL := len(curVS)
		tL := len(toVS)
		if cL < tL {
			t := make([]string, tL)
			copy(t, curVS)
			curVS = t
		} else if tL < cL {
			t := make([]string, cL)
			copy(t, toVS)
			toVS = t
		}
		for k, v := range curVS {
			to := toVS[k]
			vl := len(v)
			tl := len(to)
			if vl > tl {
				to = lpadToLength(to, vl)
			} else if vl < tl {
				v = lpadToLength(v, tl)
			}
			if v < to {
				return true
			} else if v > to {
				return false
			}
		}
		return false
	}
}
func loadFrom(path string) ([]Migration, error) {
	parentDir := filepath.Join(path, "*.migration")
	migrations, err := filepath.Glob(parentDir)
	if err != nil {
		return nil, err
	}
	sort.Slice(migrations, nearlyLexical(migrations))
	var answer []Migration
	for _, migration := range migrations {
		fmt.Printf("file name: %s\n", migration)
		as, err := toStruct(migration)
		if err != nil {
			return answer, err
		}
		fmt.Printf("The migration is %+v\n", as)
		answer = append(answer, as)
	}
	return answer, nil
}
func open(childPath string) ([]byte, string, error) {
	bytes, err := ioutil.ReadFile(childPath)
	if err != nil {
		return nil, "", err
	}
	chk := md5.Sum(bytes)
	return bytes, hex.EncodeToString(chk[:]), nil
}