github.com/btwiuse/jiri@v0.0.0-20191125065820-53353bcfef54/jiritest/fake.go (about)

     1  // Copyright 2015 The Vanadium Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package jiritest
     6  
     7  import (
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/btwiuse/jiri"
    14  	"github.com/btwiuse/jiri/gitutil"
    15  	"github.com/btwiuse/jiri/project"
    16  	"github.com/btwiuse/jiri/jiritest/xtest"
    17  )
    18  
    19  // FakeJiriRoot sets up a fake root under a tmp directory.
    20  type FakeJiriRoot struct {
    21  	X             *jiri.X
    22  	Projects      map[string]string
    23  	ProjectHashes map[string][]string
    24  	remote        string
    25  }
    26  
    27  const (
    28  	ManifestFileName    = "public"
    29  	ManifestProjectPath = "manifest"
    30  )
    31  const (
    32  	defaultDataDir      = "data"
    33  	ManifestProjectName = "manifest"
    34  )
    35  
    36  // NewFakeJiriRoot returns a new FakeJiriRoot and a cleanup closure.  The
    37  // closure must be run to cleanup temporary directories and restore the original
    38  // environment; typically it is run as a defer function.
    39  func NewFakeJiriRoot(t *testing.T) (*FakeJiriRoot, func()) {
    40  	// lockfiles are disabled in tests by defaults
    41  	jirix, cleanup := xtest.NewX(t)
    42  	fake := &FakeJiriRoot{
    43  		X:             jirix,
    44  		Projects:      map[string]string{},
    45  		ProjectHashes: make(map[string][]string),
    46  	}
    47  
    48  	// Create fake remote manifest projects.
    49  	remoteDir, err := ioutil.TempDir("", "")
    50  	if err != nil {
    51  		t.Fatalf("TempDir() failed: %v", err)
    52  	}
    53  	fake.remote = remoteDir
    54  	if err := fake.CreateRemoteProject(ManifestProjectPath); err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	// Create a fake manifest.
    58  	manifestDir := filepath.Join(remoteDir, ManifestProjectPath)
    59  	if err := os.MkdirAll(manifestDir, os.FileMode(0700)); err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	if err := fake.WriteRemoteManifest(&project.Manifest{}); err != nil {
    63  		t.Fatal(err)
    64  	}
    65  	// Add the "manifest" project to the manifest.
    66  	if err := fake.AddProject(project.Project{
    67  		Name:   ManifestProjectName,
    68  		Path:   ManifestProjectPath,
    69  		Remote: fake.Projects[ManifestProjectName],
    70  	}); err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	// Create a .jiri_manifest file which imports the manifest created above.
    74  	if err := fake.WriteJiriManifest(&project.Manifest{
    75  		Imports: []project.Import{
    76  			project.Import{
    77  				Manifest: ManifestFileName,
    78  				Name:     ManifestProjectName,
    79  				Remote:   filepath.Join(fake.remote, ManifestProjectPath),
    80  			},
    81  		},
    82  	}); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	// Update the contents of the fake instance based on  the information
    87  	// recorded in the remote manifest.
    88  	if err := fake.UpdateUniverse(false); err != nil {
    89  		t.Fatal(err)
    90  	}
    91  
    92  	return fake, func() {
    93  		cleanup()
    94  		if err := os.RemoveAll(fake.remote); err != nil {
    95  			t.Fatalf("RemoveAll(%q) failed: %v", fake.remote, err)
    96  		}
    97  	}
    98  }
    99  
   100  // AddProject adds the given project to a remote manifest.
   101  func (fake FakeJiriRoot) AddProject(project project.Project) error {
   102  	manifest, err := fake.ReadRemoteManifest()
   103  	if err != nil {
   104  		return err
   105  	}
   106  	manifest.Projects = append(manifest.Projects, project)
   107  	if err := fake.WriteRemoteManifest(manifest); err != nil {
   108  		return err
   109  	}
   110  	return nil
   111  }
   112  
   113  // AddHook adds the given hook to a remote manifest.
   114  func (fake FakeJiriRoot) AddHook(hook project.Hook) error {
   115  	manifest, err := fake.ReadRemoteManifest()
   116  	if err != nil {
   117  		return err
   118  	}
   119  	manifest.Hooks = append(manifest.Hooks, hook)
   120  	if err := fake.WriteRemoteManifest(manifest); err != nil {
   121  		return err
   122  	}
   123  	return nil
   124  }
   125  
   126  // AddPackage adds the given package to a remote manifest.
   127  func (fake FakeJiriRoot) AddPackage(pkg project.Package) error {
   128  	manifest, err := fake.ReadRemoteManifest()
   129  	if err != nil {
   130  		return err
   131  	}
   132  	manifest.Packages = append(manifest.Packages, pkg)
   133  	if err := fake.WriteRemoteManifest(manifest); err != nil {
   134  		return err
   135  	}
   136  	return nil
   137  }
   138  
   139  // DisableRemoteManifestPush disables pushes to the remote manifest
   140  // repository.
   141  func (fake FakeJiriRoot) DisableRemoteManifestPush() error {
   142  	dir := gitutil.RootDirOpt(filepath.Join(fake.remote, ManifestProjectPath))
   143  	if err := gitutil.New(fake.X, dir).CheckoutBranch("master"); err != nil {
   144  		return err
   145  	}
   146  	return nil
   147  }
   148  
   149  // EnableRemoteManifestPush enables pushes to the remote manifest
   150  // repository.
   151  func (fake FakeJiriRoot) EnableRemoteManifestPush() error {
   152  	dir := filepath.Join(fake.remote, ManifestProjectPath)
   153  	scm := gitutil.New(fake.X, gitutil.RootDirOpt(dir))
   154  	if ok, err := scm.BranchExists("non-master"); ok && err == nil {
   155  		if err := scm.CreateBranch("non-master"); err != nil {
   156  			return err
   157  		}
   158  	} else if err != nil {
   159  		return err
   160  	}
   161  	if err := scm.CheckoutBranch("non-master"); err != nil {
   162  		return err
   163  	}
   164  	return nil
   165  }
   166  
   167  // CreateRemoteProject creates a new remote project.
   168  func (fake FakeJiriRoot) CreateRemoteProject(name string) error {
   169  	projectDir := filepath.Join(fake.remote, name)
   170  	if err := os.MkdirAll(projectDir, os.FileMode(0700)); err != nil {
   171  		return err
   172  	}
   173  	if err := gitutil.New(fake.X).Init(projectDir); err != nil {
   174  		return err
   175  	}
   176  	git := gitutil.New(fake.X, gitutil.RootDirOpt(projectDir))
   177  	if err := git.Config("user.email", "john.doe@example.com"); err != nil {
   178  		return err
   179  	}
   180  	if err := git.Config("user.name", "John Doe"); err != nil {
   181  		return err
   182  	}
   183  
   184  	if err := git.CommitWithMessage("initial commit"); err != nil {
   185  		return err
   186  	}
   187  
   188  	hash, err := git.CurrentRevisionOfBranch("HEAD")
   189  	if err != nil {
   190  		return err
   191  	}
   192  	fake.ProjectHashes[name] = append(fake.ProjectHashes[name], hash)
   193  	fake.Projects[name] = projectDir
   194  	return nil
   195  }
   196  
   197  // ReadRemoteManifest read a manifest from the remote manifest project.
   198  func (fake FakeJiriRoot) ReadRemoteManifest() (*project.Manifest, error) {
   199  	path := filepath.Join(fake.remote, ManifestProjectPath, ManifestFileName)
   200  	return project.ManifestFromFile(fake.X, path)
   201  }
   202  
   203  // UpdateUniverse synchronizes the content of the Vanadium fake based
   204  // on the content of the remote manifest.
   205  func (fake FakeJiriRoot) UpdateUniverse(gc bool) error {
   206  	if err := project.UpdateUniverse(fake.X, gc, false, false, false, false, true /*run-hooks*/, true /*run-packages*/, project.DefaultHookTimeout, project.DefaultPackageTimeout); err != nil {
   207  		return err
   208  	}
   209  	return nil
   210  }
   211  
   212  // ReadJiriManifest reads the .jiri_manifest manifest.
   213  func (fake FakeJiriRoot) ReadJiriManifest() (*project.Manifest, error) {
   214  	return project.ManifestFromFile(fake.X, fake.X.JiriManifestFile())
   215  }
   216  
   217  // WriteJiriManifest writes the given manifest to the .jiri_manifest file.
   218  func (fake FakeJiriRoot) WriteJiriManifest(manifest *project.Manifest) error {
   219  	return manifest.ToFile(fake.X, fake.X.JiriManifestFile())
   220  }
   221  
   222  // WriteRemoteManifest writes the given manifest to the remote
   223  // manifest project.
   224  func (fake FakeJiriRoot) WriteRemoteManifest(manifest *project.Manifest) error {
   225  	dir := filepath.Join(fake.remote, ManifestProjectPath)
   226  	path := filepath.Join(dir, ManifestFileName)
   227  	return fake.writeManifest(manifest, dir, path)
   228  }
   229  
   230  func (fake FakeJiriRoot) writeManifest(manifest *project.Manifest, dir, path string) error {
   231  	git := gitutil.New(fake.X, gitutil.UserNameOpt("John Doe"), gitutil.UserEmailOpt("john.doe@example.com"), gitutil.RootDirOpt(dir))
   232  	if err := manifest.ToFile(fake.X, path); err != nil {
   233  		return err
   234  	}
   235  	if err := git.Add(path); err != nil {
   236  		return err
   237  	}
   238  	if err := git.Commit(); err != nil {
   239  		return err
   240  	}
   241  	hash, err := git.CurrentRevisionOfBranch("HEAD")
   242  	if err != nil {
   243  		return err
   244  	}
   245  	fake.ProjectHashes[ManifestProjectName] = append(fake.ProjectHashes[ManifestProjectName], hash)
   246  	return nil
   247  }
   248  
   249  // AddProjectOverride adds a project override into .jiri_manifest of current FakeJiriRoot.
   250  func (fake FakeJiriRoot) AddProjectOverride(name, remote, revision string) error {
   251  	m, err := fake.ReadJiriManifest()
   252  	if err != nil {
   253  		return err
   254  	}
   255  	m.ProjectOverrides = append(m.ProjectOverrides, project.Project{
   256  		Name:     name,
   257  		Remote:   remote,
   258  		Revision: revision,
   259  	})
   260  	fake.WriteJiriManifest(m)
   261  	return nil
   262  }
   263  
   264  // AddImportOverride adds a import override into .jiri_manifest of current FakeJiriRoot.
   265  func (fake FakeJiriRoot) AddImportOverride(name, remote, revision, manifest string) error {
   266  	m, err := fake.ReadJiriManifest()
   267  	if err != nil {
   268  		return err
   269  	}
   270  	m.ImportOverrides = append(m.ImportOverrides, project.Import{
   271  		Name:     name,
   272  		Remote:   remote,
   273  		Revision: revision,
   274  		Manifest: manifest,
   275  	})
   276  	fake.WriteJiriManifest(m)
   277  	return nil
   278  }