github.com/dynastymasra/migrate/v4@v4.11.0/source/httpfs/partial_driver.go (about)

     1  package httpfs
     2  
     3  import (
     4  	"io"
     5  	"net/http"
     6  	"os"
     7  	"path"
     8  	"strconv"
     9  
    10  	"github.com/golang-migrate/migrate/v4/source"
    11  )
    12  
    13  // PartialDriver is a helper service for creating new source drivers working with
    14  // http.FileSystem instances. It implements all source.Driver interface methods
    15  // except for Open(). New driver could embed this struct and add missing Open()
    16  // method.
    17  //
    18  // To prepare PartialDriver for use Init() function.
    19  type PartialDriver struct {
    20  	migrations *source.Migrations
    21  	fs         http.FileSystem
    22  	path       string
    23  }
    24  
    25  // Init prepares not initialized PartialDriver instance to read migrations from a
    26  // http.FileSystem instance and a relative path.
    27  func (p *PartialDriver) Init(fs http.FileSystem, path string) error {
    28  	root, err := fs.Open(path)
    29  	if err != nil {
    30  		return err
    31  	}
    32  
    33  	files, err := root.Readdir(0)
    34  	if err != nil {
    35  		_ = root.Close()
    36  		return err
    37  	}
    38  	if err = root.Close(); err != nil {
    39  		return err
    40  	}
    41  
    42  	ms := source.NewMigrations()
    43  	for _, file := range files {
    44  		if file.IsDir() {
    45  			continue
    46  		}
    47  
    48  		m, err := source.DefaultParse(file.Name())
    49  		if err != nil {
    50  			continue // ignore files that we can't parse
    51  		}
    52  
    53  		if !ms.Append(m) {
    54  			return source.ErrDuplicateMigration{
    55  				Migration: *m,
    56  				FileInfo:  file,
    57  			}
    58  		}
    59  	}
    60  
    61  	p.fs = fs
    62  	p.path = path
    63  	p.migrations = ms
    64  	return nil
    65  }
    66  
    67  // Close is part of source.Driver interface implementation. This is a no-op.
    68  func (p *PartialDriver) Close() error {
    69  	return nil
    70  }
    71  
    72  // First is part of source.Driver interface implementation.
    73  func (p *PartialDriver) First() (version uint, err error) {
    74  	if version, ok := p.migrations.First(); ok {
    75  		return version, nil
    76  	}
    77  	return 0, &os.PathError{
    78  		Op:   "first",
    79  		Path: p.path,
    80  		Err:  os.ErrNotExist,
    81  	}
    82  }
    83  
    84  // Prev is part of source.Driver interface implementation.
    85  func (p *PartialDriver) Prev(version uint) (prevVersion uint, err error) {
    86  	if version, ok := p.migrations.Prev(version); ok {
    87  		return version, nil
    88  	}
    89  	return 0, &os.PathError{
    90  		Op:   "prev for version " + strconv.FormatUint(uint64(version), 10),
    91  		Path: p.path,
    92  		Err:  os.ErrNotExist,
    93  	}
    94  }
    95  
    96  // Next is part of source.Driver interface implementation.
    97  func (p *PartialDriver) Next(version uint) (nextVersion uint, err error) {
    98  	if version, ok := p.migrations.Next(version); ok {
    99  		return version, nil
   100  	}
   101  	return 0, &os.PathError{
   102  		Op:   "next for version " + strconv.FormatUint(uint64(version), 10),
   103  		Path: p.path,
   104  		Err:  os.ErrNotExist,
   105  	}
   106  }
   107  
   108  // ReadUp is part of source.Driver interface implementation.
   109  func (p *PartialDriver) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) {
   110  	if m, ok := p.migrations.Up(version); ok {
   111  		body, err := p.fs.Open(path.Join(p.path, m.Raw))
   112  		if err != nil {
   113  			return nil, "", err
   114  		}
   115  		return body, m.Identifier, nil
   116  	}
   117  	return nil, "", &os.PathError{
   118  		Op:   "read up for version " + strconv.FormatUint(uint64(version), 10),
   119  		Path: p.path,
   120  		Err:  os.ErrNotExist,
   121  	}
   122  }
   123  
   124  // ReadDown is part of source.Driver interface implementation.
   125  func (p *PartialDriver) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) {
   126  	if m, ok := p.migrations.Down(version); ok {
   127  		body, err := p.fs.Open(path.Join(p.path, m.Raw))
   128  		if err != nil {
   129  			return nil, "", err
   130  		}
   131  		return body, m.Identifier, nil
   132  	}
   133  	return nil, "", &os.PathError{
   134  		Op:   "read down for version " + strconv.FormatUint(uint64(version), 10),
   135  		Path: p.path,
   136  		Err:  os.ErrNotExist,
   137  	}
   138  }