Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove polymorphic monads #219

Merged
merged 2 commits into from
Aug 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions analyzers/golang/find.go

This file was deleted.

32 changes: 17 additions & 15 deletions analyzers/golang/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/fossas/fossa-cli/analyzers/golang/resolver"
"github.com/fossas/fossa-cli/files"
"github.com/fossas/fossa-cli/log"
"github.com/fossas/fossa-cli/monad"
"github.com/pkg/errors"
)

Expand All @@ -21,22 +20,25 @@ var (
func LockfileIn(dirname string) (resolver.Type, error) {
log.Logger.Debugf("%#v", dirname)

either := monad.EitherStr{}
result := either.
Bind(findFile("godep", filepath.Join(dirname, "Godeps", "Godeps.json"))).
Bind(findFile("govendor", filepath.Join(dirname, "vendor", "vendor.json"))).
Bind(findFile("dep", filepath.Join(dirname, "Gopkg.toml"))).
Bind(findFile("vndr", filepath.Join(dirname, "vendor.conf"))).
Bind(findFile("glide", filepath.Join(dirname, "glide.yaml"))).
Bind(findFile("gdm", filepath.Join(dirname, "Godeps")))
if result.Err != nil {
log.Logger.Debugf("Err: %#v", result.Err.Error())
return "", result.Err
lockfiles := [][2]string{
[2]string{"godep", filepath.Join(dirname, "Godeps", "Godeps.json")},
[2]string{"govendor", filepath.Join(dirname, "vendor", "vendor.json")},
[2]string{"dep", filepath.Join(dirname, "Gopkg.toml")},
[2]string{"vndr", filepath.Join(dirname, "vendor.conf")},
[2]string{"glide", filepath.Join(dirname, "glide.yaml")},
[2]string{"gdm", filepath.Join(dirname, "Godeps")},
}
if result.Result == "" {
return "", ErrNoLockfileInDir

for _, lockfile := range lockfiles {
ok, err := files.Exists(lockfile[1])
if err != nil {
return "", err
}
if ok {
return resolver.Type(lockfile[0]), nil
}
}
return resolver.Type(result.Result), nil
return "", ErrNoLockfileInDir
}

// NearestLockfile returns the type and directory of the nearest lockfile in an
Expand Down
2 changes: 1 addition & 1 deletion analyzers/golang/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (a *Analyzer) Project(pkg string) (Project, error) {
tool, manifestDir, err := NearestLockfile(dir)

// Find the nearest VCS repository.
_, repoRoot, err := vcs.NearestVCS(dir)
_, repoRoot, err := vcs.Nearest(dir)
if err != nil {
return Project{}, err
}
Expand Down
13 changes: 0 additions & 13 deletions cli.go

This file was deleted.

16 changes: 16 additions & 0 deletions files/files_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package files_test

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"

"github.com/fossas/fossa-cli/files"
)

func TestNonExistentParentIsNotErr(t *testing.T) {
ok, err := files.Exists(filepath.Join("testdata", "parent", "does", "not", "exist", "file"))
assert.NoError(t, err)
assert.False(t, ok)
}
20 changes: 0 additions & 20 deletions files/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ package files
import (
"errors"
"path/filepath"

"github.com/fossas/fossa-cli/monad"
)

// blaf
var (
ErrDirNotFound = errors.New("no directory found during walk")
ErrStopWalk = errors.New("WalkUp: stop")
Expand Down Expand Up @@ -50,20 +47,3 @@ func WalkUp(startdir string, walker WalkUpFunc) (string, error) {
}
return "", ErrDirNotFound
}

// finder, bindFinder, and friends are EitherStr functions for finding whether
// one of many files exist.
type finder func(pathElems ...string) (bool, error)

func BindFinder(name string, find finder, pathElems ...string) monad.EitherStrFunc {
return func(prev string) (string, error) {
ok, err := find(pathElems...)
if err != nil {
return "", err
}
if ok {
return name, nil
}
return prev, nil
}
}
54 changes: 0 additions & 54 deletions monad/monad.go

This file was deleted.

28 changes: 0 additions & 28 deletions vcs/find.go

This file was deleted.

34 changes: 34 additions & 0 deletions vcs/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package vcs

// VCS represents a type of version control system.
type VCS int

const (
_ VCS = iota
Subversion
Git
Mercurial
Bazaar
)

var Types = [4]VCS{
Subversion,
Git,
Mercurial,
Bazaar,
}

func MetadataFolder(vcs VCS) string {
switch vcs {
case Subversion:
return ".svn"
case Git:
return ".git"
case Mercurial:
return ".hg"
case Bazaar:
return ".bzr"
default:
return ""
}
}
54 changes: 25 additions & 29 deletions vcs/vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import (
"errors"
"path/filepath"

"github.com/fossas/fossa-cli"
"github.com/fossas/fossa-cli/errutil"
"github.com/fossas/fossa-cli/files"
"github.com/fossas/fossa-cli/monad"
)

// Errors that occur when finding VCS repositories.
Expand All @@ -18,63 +16,61 @@ var (
ErrNoNearestVCS = errors.New("could not find nearest VCS repository in directory")
)

// VCSIn returns the type of VCS repository rooted at a directory, or
// In returns the type of VCS repository rooted at a directory, or
// ErrNoVCSInDir if none is found.
func vcsIn(dirname string) (cli.VCS, error) {
either := monad.EitherVCS{}
result := either.
BindVCS(findVCSFolder(cli.Git, filepath.Join(dirname, ".git"))).
BindVCS(findVCSFolder(cli.Subversion, filepath.Join(dirname, ".svn"))).
BindVCS(findVCSFolder(cli.Mercurial, filepath.Join(dirname, ".hg"))).
BindVCS(findVCSFolder(cli.Bazaar, filepath.Join(dirname, ".bzr")))
if result.Err != nil {
return 0, result.Err
}
if result.Result == 0 {
return 0, ErrNoVCSInDir
func In(dirname string) (VCS, error) {
for _, vcs := range Types {
ok, err := files.ExistsFolder(filepath.Join(dirname, MetadataFolder(vcs)))
if err != nil {
return 0, err
}
if ok {
return vcs, nil
}
}
return result.Result, nil
return 0, ErrNoVCSInDir
}

// NearestVCS returns the type and directory of the nearest VCS repository
// Nearest returns the type and directory of the nearest VCS repository
// containing the directory, or ErrNoNearestVCS if none is found.
func NearestVCS(dirname string) (vcsType cli.VCS, vcsDir string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the move away from named returns?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just avoid them where possible, because assignment in Go follows unintuitive shadowing rules. I usually only use named returns when returning multiple values of the same type.

Example of weird shadowing:

func Foo() (bar string) {
	bar, err := Baz() // This is a _different_ bar, shadowing the original
	return            // Implicitly returns `bar = ""`, the string type's zero value
}

vcsDir, err = files.WalkUp(dirname, func(d string) error {
tool, err := vcsIn(d)
func Nearest(dirname string) (VCS, string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 to this and other renames

var vcs VCS
dir, err := files.WalkUp(dirname, func(d string) error {
tool, err := In(d)
if err == ErrNoVCSInDir {
return nil
}
if err != nil {
return err
}
vcsType = tool
vcs = tool
return files.ErrStopWalk
})
if err == files.ErrDirNotFound {
return 0, "", ErrNoNearestVCS
}
return vcsType, vcsDir, err
return vcs, dir, err
}

// GetRepository returns the location of the repository containing dirname,
// errutil.ErrRepositoryNotFound if none is found, or errutil.ErrNotImplemented
// if an unsupported VCS is found.
func GetRepository(dirname string) (string, error) {
vcsType, vcsDir, err := NearestVCS(dirname)
vcs, dir, err := Nearest(dirname)
if err == ErrNoNearestVCS {
return "", errutil.ErrRepositoryNotFound
}
if err != nil {
return "", err
}
switch vcsType {
case cli.Git:
return vcsDir, nil
case cli.Subversion:
switch vcs {
case Git:
return dir, nil
case Subversion:
return "", errutil.ErrNotImplemented
case cli.Mercurial:
case Mercurial:
return "", errutil.ErrNotImplemented
case cli.Bazaar:
case Bazaar:
return "", errutil.ErrNotImplemented
default:
return "", errutil.ErrNotImplemented
Expand Down