sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/clonerefs/parse.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package clonerefs
    18  
    19  import (
    20  	"fmt"
    21  	"strconv"
    22  	"strings"
    23  
    24  	prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1"
    25  )
    26  
    27  // ParseRefs parses a human-provided string into the repo
    28  // that should be cloned and the refs that need to be
    29  // checked out once it is. The format is:
    30  //
    31  //	org,repo=base-ref[:base-sha][,pull-id[:pull-sha[:pull-ref]]]...
    32  //
    33  // For the base ref and pull IDs, a SHA may optionally be
    34  // provided or may be omitted for the latest available SHA.
    35  // Examples:
    36  //
    37  //	kubernetes,test-infra=master
    38  //	kubernetes,test-infra=master:abcde12
    39  //	kubernetes,test-infra=master:abcde12,34
    40  //	kubernetes,test-infra=master:abcde12,34:fghij56
    41  //	kubernetes,test-infra=master,34:fghij56
    42  //	kubernetes,test-infra=master:abcde12,34:fghij56,78
    43  //	gerrit,test-infra=master:abcde12,34:fghij56:refs/changes/00/123/1
    44  func ParseRefs(value string) (*prowapi.Refs, error) {
    45  	gitRef := &prowapi.Refs{}
    46  	values := strings.SplitN(value, "=", 2)
    47  	if len(values) != 2 {
    48  		return gitRef, fmt.Errorf("refspec %s invalid: does not contain '='", value)
    49  	}
    50  	info := values[0]
    51  	allRefs := values[1]
    52  
    53  	infoValues := strings.SplitN(info, ",", 2)
    54  	if len(infoValues) != 2 {
    55  		return gitRef, fmt.Errorf("refspec %s invalid: does not contain 'org,repo' as prefix", value)
    56  	}
    57  	gitRef.Org = infoValues[0]
    58  	gitRef.Repo = infoValues[1]
    59  
    60  	refValues := strings.Split(allRefs, ",")
    61  	if len(refValues) == 1 && refValues[0] == "" {
    62  		return gitRef, fmt.Errorf("refspec %s invalid: does not contain any refs", value)
    63  	}
    64  	baseRefParts := strings.Split(refValues[0], ":")
    65  	if len(baseRefParts) != 1 && len(baseRefParts) != 2 {
    66  		return gitRef, fmt.Errorf("refspec %s invalid: malformed base ref", refValues[0])
    67  	}
    68  	gitRef.BaseRef = baseRefParts[0]
    69  	if len(baseRefParts) == 2 {
    70  		gitRef.BaseSHA = baseRefParts[1]
    71  	}
    72  	for _, refValue := range refValues[1:] {
    73  		refParts := strings.Split(refValue, ":")
    74  		if len(refParts) == 0 || len(refParts) > 3 {
    75  			return gitRef, fmt.Errorf("refspec %s invalid: malformed pull ref", refValue)
    76  		}
    77  		pullNumber, err := strconv.Atoi(refParts[0])
    78  		if err != nil {
    79  			return gitRef, fmt.Errorf("refspec %s invalid: pull request identifier not a number: %w", refValue, err)
    80  		}
    81  		pullRef := prowapi.Pull{
    82  			Number: pullNumber,
    83  		}
    84  		if len(refParts) > 1 {
    85  			pullRef.SHA = refParts[1]
    86  		}
    87  		if len(refParts) > 2 {
    88  			pullRef.Ref = refParts[2]
    89  		}
    90  		gitRef.Pulls = append(gitRef.Pulls, pullRef)
    91  	}
    92  
    93  	return gitRef, nil
    94  }