github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/testing/fixtures/fixtures.go (about)

     1  package fixtures
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"sync"
     7  
     8  	"github.com/apex/log"
     9  	git "gopkg.in/src-d/go-git.v4"
    10  	"gopkg.in/src-d/go-git.v4/plumbing"
    11  
    12  	"github.com/fossas/fossa-cli/files"
    13  )
    14  
    15  // Project describes how to download, build, and analyse a fixture.
    16  type Project struct {
    17  	Name   string
    18  	URL    string
    19  	Commit string
    20  	// Ref points to a particular reference. It will always be preferred over Commit
    21  	Ref           string
    22  	ModuleOptions map[string]interface{}
    23  	Env           map[string]string
    24  }
    25  
    26  // Directory returns the path to test fixtures.
    27  func Directory() string {
    28  	return filepath.Join(os.TempDir(), "fossa-cli-fixtures")
    29  }
    30  
    31  // ProjectInitializer defines how a single project should be initialized after
    32  // it has been cloned.
    33  type ProjectInitializer func(p Project, projectDir string) error
    34  
    35  // Initialize clones and initializes a fixture into a directory.
    36  func Initialize(baseDir string, projects []Project, initializer ProjectInitializer) {
    37  	// Exit early when fixtures already exist.
    38  	// This is a bit scary since we don't validate whether the fixtures are
    39  	// correct, but corrupted fixtures should cause erratic test failures. If we
    40  	// wanted to validate fixtures, we might want to store e.g. a hash of the
    41  	// fixture contents and verify against that (or validate the commit of the Git
    42  	// repositories).
    43  	baseDirExists, err := files.ExistsFolder(baseDir)
    44  	if err == nil && baseDirExists {
    45  		log.Debug(baseDir + " already exists, assuming fixtures OK")
    46  		return
    47  	}
    48  
    49  	// Make the fixtures directory.
    50  	err = os.MkdirAll(baseDir, os.FileMode(0700))
    51  	if err != nil {
    52  		panic(err)
    53  	}
    54  
    55  	// Clone and initialize in parallel.
    56  	var waitGroup sync.WaitGroup
    57  	waitGroup.Add(len(projects))
    58  	for _, p := range projects {
    59  		go func(project Project) {
    60  			defer waitGroup.Done()
    61  
    62  			projectDir := filepath.Join(baseDir, project.Name)
    63  			if project.Ref != "" {
    64  				_, err := git.PlainClone(projectDir, false, &git.CloneOptions{
    65  					URL:               project.URL,
    66  					Depth:             1,
    67  					RecurseSubmodules: 1,
    68  					ReferenceName:     plumbing.ReferenceName(project.Ref),
    69  					SingleBranch:      true,
    70  				})
    71  				if err != nil {
    72  					panic(err)
    73  				}
    74  			} else {
    75  				repo, err := git.PlainClone(projectDir, false, &git.CloneOptions{
    76  					URL:               project.URL,
    77  					RecurseSubmodules: 1,
    78  				})
    79  				if err != nil {
    80  					panic(err)
    81  				}
    82  
    83  				worktree, err := repo.Worktree()
    84  				if err != nil {
    85  					panic(err)
    86  				}
    87  				err = worktree.Checkout(&git.CheckoutOptions{
    88  					Hash: plumbing.NewHash(project.Commit),
    89  				})
    90  				if err != nil {
    91  					panic(err)
    92  				}
    93  			}
    94  
    95  			err = initializer(project, projectDir)
    96  			if err != nil {
    97  				panic(err)
    98  			}
    99  		}(p)
   100  	}
   101  
   102  	waitGroup.Wait()
   103  }