github.com/btwiuse/jiri@v0.0.0-20191125065820-53353bcfef54/project/state.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 project 6 7 import ( 8 "fmt" 9 10 "github.com/btwiuse/jiri" 11 "github.com/btwiuse/jiri/gitutil" 12 "github.com/btwiuse/jiri/tool" 13 ) 14 15 type ReferenceState struct { 16 Name string 17 Revision string 18 } 19 20 type BranchState struct { 21 *ReferenceState 22 Tracking *ReferenceState 23 } 24 25 type ProjectState struct { 26 Branches []BranchState 27 CurrentBranch BranchState 28 HasUncommitted bool 29 HasUntracked bool 30 Project Project 31 } 32 33 func setProjectState(jirix *jiri.X, state *ProjectState, checkDirty bool, ch chan<- error) { 34 var err error 35 scm := gitutil.New(jirix, gitutil.RootDirOpt(state.Project.Path)) 36 branches, err := scm.GetAllBranchesInfo() 37 if err != nil { 38 ch <- err 39 return 40 } 41 state.CurrentBranch = BranchState{ 42 &ReferenceState{ 43 Name: "", 44 }, 45 nil, 46 } 47 for _, branch := range branches { 48 b := BranchState{ 49 &ReferenceState{ 50 Name: branch.Name, 51 Revision: branch.Revision, 52 }, 53 nil, 54 } 55 if branch.Tracking != nil { 56 b.Tracking = &ReferenceState{ 57 Name: branch.Tracking.Name, 58 Revision: branch.Tracking.Revision, 59 } 60 } 61 state.Branches = append(state.Branches, b) 62 if branch.IsHead { 63 state.CurrentBranch = b 64 } 65 } 66 if state.CurrentBranch.Name == "" { 67 if state.CurrentBranch.Revision, err = scm.CurrentRevision(); err != nil { 68 ch <- err 69 return 70 } 71 } 72 if checkDirty { 73 state.HasUncommitted, err = scm.HasUncommittedChanges() 74 if err != nil { 75 ch <- fmt.Errorf("Cannot get uncommited changes for project %q: %v", state.Project.Name, err) 76 return 77 } 78 state.HasUntracked, err = scm.HasUntrackedFiles() 79 if err != nil { 80 ch <- fmt.Errorf("Cannot get untracked changes for project %q: %v", state.Project.Name, err) 81 return 82 } 83 } 84 ch <- nil 85 } 86 87 func GetProjectStates(jirix *jiri.X, projects Projects, checkDirty bool) (map[ProjectKey]*ProjectState, error) { 88 jirix.TimerPush("Get project states") 89 defer jirix.TimerPop() 90 states := make(map[ProjectKey]*ProjectState, len(projects)) 91 sem := make(chan error, len(projects)) 92 for key, project := range projects { 93 state := &ProjectState{ 94 Project: project, 95 } 96 states[key] = state 97 // jirix is not threadsafe, so we make a clone for each goroutine. 98 go setProjectState(jirix.Clone(tool.ContextOpts{}), state, checkDirty, sem) 99 } 100 for _ = range projects { 101 err := <-sem 102 if err != nil { 103 return nil, err 104 } 105 } 106 return states, nil 107 } 108 109 func GetProjectState(jirix *jiri.X, project Project, checkDirty bool) (*ProjectState, error) { 110 sem := make(chan error, 1) 111 state := &ProjectState{ 112 Project: project, 113 } 114 setProjectState(jirix, state, checkDirty, sem) 115 return state, <-sem 116 }