Skip to content

Commit

Permalink
Introduce NewContext to validate CLI flags
Browse files Browse the repository at this point in the history
  • Loading branch information
aswinkarthik committed Oct 8, 2019
1 parent 037f723 commit 36438e4
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 244 deletions.
176 changes: 87 additions & 89 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,107 @@ import (

// Context is to store all command line Flags.
type Context struct {
PrimaryKeyPositions []int
ValueColumnPositions []int
IncludeColumnPositions []int
Format string
BaseFilename string
DeltaFilename string
fs afero.Fs
primaryKeyPositions []int
valueColumnPositions []int
includeColumnPositions []int
format string
baseFilename string
deltaFilename string
baseFile afero.File
deltaFile afero.File
recordCount int
}

// NewContext can take all CLI flags and create a cmd.Context
// Validations are done as part of this.
// File pointers are created too.
func NewContext(
fs afero.Fs,
primaryKeyPositions []int,
valueColumnPositions []int,
ignoreValueColumnPositions []int,
includeColumnPositions []int,
format string,
baseFilename string,
deltaFilename string,
) (*Context, error) {
baseRecordCount, err := getColumnsCount(fs, baseFilename)
if err != nil {
return nil, fmt.Errorf("error in base-file: %v", err)
}

deltaRecordCount, err := getColumnsCount(fs, deltaFilename)
if err != nil {
return nil, fmt.Errorf("error in delta-file: %v", err)
}

if baseRecordCount != deltaRecordCount {
return nil, fmt.Errorf("base-file and delta-file columns count do not match")
}

baseFile, err := fs.Open(baseFilename)
if err != nil {
return nil, err
}
deltaFile, err := fs.Open(deltaFilename)
if err != nil {
return nil, err
}
ctx := &Context{
fs: fs,
primaryKeyPositions: primaryKeyPositions,
valueColumnPositions: valueColumnPositions,
includeColumnPositions: includeColumnPositions,
format: format,
baseFilename: baseFilename,
deltaFilename: deltaFilename,
baseFile: baseFile,
deltaFile: deltaFile,
recordCount: baseRecordCount,
}

if err := ctx.validate(); err != nil {
return nil, fmt.Errorf("validation failed: %v", err)
}

return ctx, nil
}

// GetPrimaryKeys is to return the --primary-key flags as digest.Positions array.
func (c *Context) GetPrimaryKeys() digest.Positions {
if len(c.PrimaryKeyPositions) > 0 {
return c.PrimaryKeyPositions
if len(c.primaryKeyPositions) > 0 {
return c.primaryKeyPositions
}
return []int{0}
}

// GetValueColumns is to return the --columns flags as digest.Positions array.
func (c *Context) GetValueColumns() digest.Positions {
if len(c.ValueColumnPositions) > 0 {
return c.ValueColumnPositions
if len(c.valueColumnPositions) > 0 {
return c.valueColumnPositions
}
return []int{}
}

// GetIncludeColumnPositions is to return the --include flags as digest.Positions array.
// If empty, it is value columns
func (c Context) GetIncludeColumnPositions() digest.Positions {
if len(c.IncludeColumnPositions) > 0 {
return c.IncludeColumnPositions
if len(c.includeColumnPositions) > 0 {
return c.includeColumnPositions
}
return c.GetValueColumns()
}

// Validate validates the context object
// validate validates the context object
// and returns error if not valid.
func (c *Context) Validate(fs afero.Fs) error {
func (c *Context) validate() error {
{
// format validation

formatFound := false
for _, format := range allFormats {
if strings.ToLower(c.Format) == format {
if strings.ToLower(c.format) == format {
formatFound = true
}
}
Expand All @@ -65,62 +122,17 @@ func (c *Context) Validate(fs afero.Fs) error {
}

{
// base-file validation

if exists, err := afero.Exists(fs, c.BaseFilename); err != nil {
return fmt.Errorf("error reading base-file %s: %v", c.BaseFilename, err)
} else if !exists {
return fmt.Errorf("base-file %s does not exits", c.BaseFilename)
}

if isDir, err := afero.IsDir(fs, c.BaseFilename); err != nil {
return fmt.Errorf("error reading base-file %s: %v", c.BaseFilename, err)
} else if isDir {
return fmt.Errorf("base-file %s should be a file", c.BaseFilename)
}
}

{
// delta file validation

if exists, err := afero.Exists(fs, c.DeltaFilename); err != nil {
return fmt.Errorf("error reading delta-file %s: %v", c.DeltaFilename, err)
} else if !exists {
return fmt.Errorf("delta-file %s does not exits", c.DeltaFilename)
}

if isDir, err := afero.IsDir(fs, c.DeltaFilename); err != nil {
return fmt.Errorf("error reading delta-file %s: %v", c.DeltaFilename, err)
} else if isDir {
return fmt.Errorf("delta-file %s should be a file", c.DeltaFilename)
}
}

{
baseRecordCount, err := getColumnsCount(fs, c.BaseFilename)
if err != nil {
return err
}
deltaRecordCount, err := getColumnsCount(fs, c.DeltaFilename)
if err != nil {
return err
}

if baseRecordCount != deltaRecordCount {
return fmt.Errorf("base-file and delta-file columns count do not match")
}

comparator := func(element int) bool {
return element < baseRecordCount
return element < c.recordCount
}

if !assertAll(c.PrimaryKeyPositions, comparator) {
if !assertAll(c.primaryKeyPositions, comparator) {
return fmt.Errorf("--primary-key positions are out of bounds")
}
if !assertAll(c.IncludeColumnPositions, comparator) {
if !assertAll(c.includeColumnPositions, comparator) {
return fmt.Errorf("--include positions are out of bounds")
}
if !assertAll(c.ValueColumnPositions, comparator) {
if !assertAll(c.valueColumnPositions, comparator) {
return fmt.Errorf("--columns positions are out of bounds")
}
}
Expand Down Expand Up @@ -148,7 +160,7 @@ func getColumnsCount(fs afero.Fs, filename string) (int, error) {
record, err := csvReader.Read()
if err != nil {
if err == io.EOF {
return 0, fmt.Errorf("unable to process headers from csv file. EOF reached")
return 0, fmt.Errorf("unable to process headers from csv file. EOF reached. invalid CSV file")
}
return 0, err
}
Expand All @@ -158,37 +170,23 @@ func getColumnsCount(fs afero.Fs, filename string) (int, error) {

// BaseDigestConfig creates a digest.Context from cmd.Context
// that is needed to start the diff process
func (c *Context) BaseDigestConfig(fs afero.Fs) (digest.Config, error) {
baseFile, err := fs.Open(c.BaseFilename)
if err != nil {
return digest.Config{}, err
}

c.baseFile = baseFile

func (c *Context) BaseDigestConfig() (digest.Config, error) {
return digest.Config{
Reader: baseFile,
Value: c.ValueColumnPositions,
Key: c.PrimaryKeyPositions,
Include: c.IncludeColumnPositions,
Reader: c.baseFile,
Value: c.valueColumnPositions,
Key: c.primaryKeyPositions,
Include: c.includeColumnPositions,
}, nil
}

// DeltaDigestConfig creates a digest.Context from cmd.Context
// that is needed to start the diff process
func (c *Context) DeltaDigestConfig(fs afero.Fs) (digest.Config, error) {
deltaFile, err := fs.Open(c.DeltaFilename)
if err != nil {
return digest.Config{}, err
}

c.baseFile = deltaFile

func (c *Context) DeltaDigestConfig() (digest.Config, error) {
return digest.Config{
Reader: deltaFile,
Value: c.ValueColumnPositions,
Key: c.PrimaryKeyPositions,
Include: c.IncludeColumnPositions,
Reader: c.deltaFile,
Value: c.valueColumnPositions,
Key: c.primaryKeyPositions,
Include: c.includeColumnPositions,
}, nil
}

Expand Down
Loading

0 comments on commit 36438e4

Please sign in to comment.