v.io/jiri@v0.0.0-20160715023856-abfb8b131290/gerrit/multipart.go (about) 1 // Copyright 2016 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 gerrit 6 7 import ( 8 "fmt" 9 "sort" 10 ) 11 12 // MultiPartCLInfo contains data used to process multiple cls across 13 // different projects. 14 type MultiPartCLInfo struct { 15 Topic string 16 Index int // This should be 1-based. 17 Total int 18 } 19 20 // MultiPartCLSet represents a set of CLs that spans multiple projects. 21 type MultiPartCLSet struct { 22 parts map[int]Change // Indexed by cl's part index. 23 expectedTotal int 24 expectedTopic string 25 } 26 27 // NewMultiPartCLSet creates a new instance of MultiPartCLSet. 28 func NewMultiPartCLSet() *MultiPartCLSet { 29 return &MultiPartCLSet{ 30 parts: map[int]Change{}, 31 expectedTotal: -1, 32 expectedTopic: "", 33 } 34 } 35 36 // AddCL adds a CL to the set after it passes a series of checks. 37 func (s *MultiPartCLSet) AddCL(cl Change) error { 38 if cl.MultiPart == nil { 39 return fmt.Errorf("no multi part info found: %#v", cl) 40 } 41 multiPartInfo := cl.MultiPart 42 if s.expectedTotal < 0 { 43 s.expectedTotal = multiPartInfo.Total 44 } 45 if s.expectedTopic == "" { 46 s.expectedTopic = multiPartInfo.Topic 47 } 48 if s.expectedTotal != multiPartInfo.Total { 49 return fmt.Errorf("inconsistent total number of cls in this set: want %d, got %d", s.expectedTotal, multiPartInfo.Total) 50 } 51 if s.expectedTopic != multiPartInfo.Topic { 52 return fmt.Errorf("inconsistent cl topics in this set: want %s, got %s", s.expectedTopic, multiPartInfo.Topic) 53 } 54 if existingCL, ok := s.parts[multiPartInfo.Index]; ok { 55 return fmt.Errorf("duplicated cl part %d found:\ncl to add: %v\nexisting cl:%v", multiPartInfo.Index, cl, existingCL) 56 } 57 s.parts[multiPartInfo.Index] = cl 58 return nil 59 } 60 61 // Complete returns whether the current set has all the cl parts it needs. 62 func (s *MultiPartCLSet) Complete() bool { 63 return len(s.parts) == s.expectedTotal 64 } 65 66 // CLs returns a list of CLs in this set sorted by their part number. 67 func (s *MultiPartCLSet) CLs() CLList { 68 ret := CLList{} 69 sortedKeys := []int{} 70 for part := range s.parts { 71 sortedKeys = append(sortedKeys, part) 72 } 73 sort.Ints(sortedKeys) 74 for _, part := range sortedKeys { 75 ret = append(ret, s.parts[part]) 76 } 77 return ret 78 }