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 }