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  }