func (mf MigrationFiles) Swap(i, j int) {
	mf[i], mf[j] = mf[j], mf[i]
}
Swap swaps the elements with indexes i and j.
Required by Sort Interface{}
package file
import (
	"bytes"
	"errors"
	"fmt"
	"go/token"
	"io/ioutil"
	"path"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"github.com/mattes/migrate/migrate/direction"
)
var filenameRegex = `^([0-9]+)_(.*)\.(up|down)\.%s$`
func FilenameRegex(filenameExtension string) *regexp.Regexp {
	return regexp.MustCompile(fmt.Sprintf(filenameRegex, filenameExtension))
}
type File struct {
	Path string
	FileName string
	Version uint64
	Name string
	Content []byte
	Direction direction.Direction
}
type Files []File
type MigrationFile struct {
	Version uint64
	UpFile *File
	DownFile *File
}
type MigrationFiles []MigrationFile
func (f *File) ReadContent() error {
	if len(f.Content) == 0 {
		content, err := ioutil.ReadFile(path.Join(f.Path, f.FileName))
		if err != nil {
			return err
		}
		f.Content = content
	}
	return nil
}
func (mf *MigrationFiles) ToFirstFrom(version uint64) (Files, error) {
	sort.Sort(sort.Reverse(mf))
	files := make(Files, 0)
	for _, migrationFile := range *mf {
		if migrationFile.Version <= version && migrationFile.DownFile != nil {
			files = append(files, *migrationFile.DownFile)
		}
	}
	return files, nil
}
func (mf *MigrationFiles) ToLastFrom(version uint64) (Files, error) {
	sort.Sort(mf)
	files := make(Files, 0)
	for _, migrationFile := range *mf {
		if migrationFile.Version > version && migrationFile.UpFile != nil {
			files = append(files, *migrationFile.UpFile)
		}
	}
	return files, nil
}
func (mf *MigrationFiles) From(version uint64, relativeN int) (Files, error) {
	var d direction.Direction
	if relativeN > 0 {
		d = direction.Up
	} else if relativeN < 0 {
		d = direction.Down
	} else {  
		return nil, nil
	}
	if d == direction.Down {
		sort.Sort(sort.Reverse(mf))
	} else {
		sort.Sort(mf)
	}
	files := make(Files, 0)
	counter := relativeN
	if relativeN < 0 {
		counter = relativeN * -1
	}
	for _, migrationFile := range *mf {
		if counter > 0 {
			if d == direction.Up && migrationFile.Version > version && migrationFile.UpFile != nil {
				files = append(files, *migrationFile.UpFile)
				counter--
			} else if d == direction.Down && migrationFile.Version <= version && migrationFile.DownFile != nil {
				files = append(files, *migrationFile.DownFile)
				counter--
			}
		} else {
			break
		}
	}
	return files, nil
}
func ReadMigrationFiles(path string, filenameRegex *regexp.Regexp) (files MigrationFiles, err error) {
	ioFiles, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}
	type tmpFile struct {
		version  uint64
		name     string
		filename string
		d        direction.Direction
	}
	tmpFiles := make([]*tmpFile, 0)
	tmpFileMap := map[uint64]map[direction.Direction]tmpFile{}
	for _, file := range ioFiles {
		version, name, d, err := parseFilenameSchema(file.Name(), filenameRegex)
		if err == nil {
			if _, ok := tmpFileMap[version]; !ok {
				tmpFileMap[version] = map[direction.Direction]tmpFile{}
			}
			if existing, ok := tmpFileMap[version][d]; !ok {
				tmpFileMap[version][d] = tmpFile{version: version, name: name, filename: file.Name(), d: d}
			} else {
				return nil, fmt.Errorf("duplicate migration file version %d : %q and %q", version, existing.filename, file.Name())
			}
			tmpFiles = append(tmpFiles, &tmpFile{version, name, file.Name(), d})
		}
	}
	parsedVersions := make(map[uint64]bool)
	newFiles := make(MigrationFiles, 0)
	for _, file := range tmpFiles {
		if _, ok := parsedVersions[file.version]; !ok {
			migrationFile := MigrationFile{
				Version: file.version,
			}
			var lookFordirection direction.Direction
			switch file.d {
			case direction.Up:
				migrationFile.UpFile = &File{
					Path:      path,
					FileName:  file.filename,
					Version:   file.version,
					Name:      file.name,
					Content:   nil,
					Direction: direction.Up,
				}
				lookFordirection = direction.Down
			case direction.Down:
				migrationFile.DownFile = &File{
					Path:      path,
					FileName:  file.filename,
					Version:   file.version,
					Name:      file.name,
					Content:   nil,
					Direction: direction.Down,
				}
				lookFordirection = direction.Up
			default:
				return nil, errors.New("Unsupported direction.Direction Type")
			}
			for _, file2 := range tmpFiles {
				if file2.version == file.version && file2.d == lookFordirection {
					switch lookFordirection {
					case direction.Up:
						migrationFile.UpFile = &File{
							Path:      path,
							FileName:  file2.filename,
							Version:   file.version,
							Name:      file2.name,
							Content:   nil,
							Direction: direction.Up,
						}
					case direction.Down:
						migrationFile.DownFile = &File{
							Path:      path,
							FileName:  file2.filename,
							Version:   file.version,
							Name:      file2.name,
							Content:   nil,
							Direction: direction.Down,
						}
					}
					break
				}
			}
			newFiles = append(newFiles, migrationFile)
			parsedVersions[file.version] = true
		}
	}
	sort.Sort(newFiles)
	return newFiles, nil
}
func parseFilenameSchema(filename string, filenameRegex *regexp.Regexp) (version uint64, name string, d direction.Direction, err error) {
	matches := filenameRegex.FindStringSubmatch(filename)
	if len(matches) != 4 {
		return 0, "", 0, errors.New("Unable to parse filename schema")
	}
	version, err = strconv.ParseUint(matches[1], 10, 0)
	if err != nil {
		return 0, "", 0, fmt.Errorf("Unable to parse version '%v' in filename schema", matches[0])
	}
	if matches[3] == "up" {
		d = direction.Up
	} else if matches[3] == "down" {
		d = direction.Down
	} else {
		return 0, "", 0, fmt.Errorf("Unable to parse up|down '%v' in filename schema", matches[3])
	}
	return version, matches[2], d, nil
}
func (mf MigrationFiles) Len() int {
	return len(mf)
}
func (mf MigrationFiles) Less(i, j int) bool {
	return mf[i].Version < mf[j].Version
}