github.com/abayer/test-infra@v0.0.5/experiment/bootstrap/repos.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 main
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  	"strings"
    23  )
    24  
    25  // Repo contains the components of git repo refs used in bootstrap
    26  type Repo struct {
    27  	Name   string
    28  	Branch string
    29  	Pull   string
    30  }
    31  
    32  // utility method used below, checks a PULL_REFS for `:`
    33  func refHasSHAs(ref string) bool {
    34  	return strings.Contains(ref, ":")
    35  }
    36  
    37  // GitBasePath returns the base git path associated with the repo,
    38  // this does not include the branch or pull.
    39  // If ssh is true this assumes git@ is the appropriate user.
    40  // TODO(bentheelder): do we want to continue to assume git@ for ssh in the future?
    41  // This works fine for GitHub and matches jenkins/bootstrap.py's `repository(..)`
    42  func (r *Repo) GitBasePath(ssh bool) string {
    43  	// TODO(bentheelder): perhaps this should contain a map of known prefix
    44  	// replacements instead so that supporting other repos is easier?
    45  	path := r.Name
    46  	if strings.HasPrefix(path, "k8s.io/") {
    47  		path = "github.com/kubernetes/" + strings.TrimPrefix(path, "k8s.io/")
    48  	}
    49  	if ssh {
    50  		if !refHasSHAs(path) {
    51  			path = strings.Replace(path, "/", ":", 1)
    52  		}
    53  		return "git@" + path
    54  	}
    55  	return "https://" + path
    56  }
    57  
    58  // PullNumbers converts a Pull's list string into a slice of PR number strings
    59  // NOTE: this assumes that if there are pull requests specified that Repo.Pull
    60  // looks something like: `master:hash,prNum:hash,prNum:hash,...`
    61  func (r *Repo) PullNumbers() []string {
    62  	if refHasSHAs(r.Pull) {
    63  		res := []string{}
    64  		parts := strings.Split(r.Pull, ",")
    65  		for _, part := range parts {
    66  			res = append(res, strings.Split(part, ":")[0])
    67  		}
    68  		return res[1:]
    69  	}
    70  	return []string{}
    71  }
    72  
    73  // Repos is a slice of Repo where Repos[0] is the main repo
    74  type Repos []Repo
    75  
    76  // Main returns the primary repo in a Repos produced by ParseRepos
    77  func (r Repos) Main() *Repo {
    78  	if len(r) == 0 {
    79  		return nil
    80  	}
    81  	return &r[0]
    82  }
    83  
    84  // ParseRepos converts the refs related arguments to []Repo
    85  // each repoArgs is expect to be "name=branch:commit,branch:commit"
    86  // with one or more comma separated "branch:commit".
    87  // EG: "k8s.io/kubernetes=master:42e2ca8c18c93ba25eb0e5bd02ecba2eaa05e871,52057:b4f639f57ae0a89cdf1b43d1810b617c76f4b1b3"
    88  func ParseRepos(repoArgs []string) (Repos, error) {
    89  	repos := []Repo{}
    90  	re := regexp.MustCompile(`([^=]+)(=([^:,~^\s]+(:[0-9a-fA-F]+)?(,|$))+)?$`)
    91  	for _, repoArg := range repoArgs {
    92  		match := re.FindStringSubmatch(repoArg)
    93  		if len(match) == 0 {
    94  			return nil, fmt.Errorf("could not parse repo: %s, %v", repoArg, repos)
    95  		}
    96  		thisRepo := match[1]
    97  		// default to master
    98  		if match[2] == "" {
    99  			repos = append(repos, Repo{
   100  				Name:   thisRepo,
   101  				Branch: "master",
   102  				Pull:   "",
   103  			})
   104  			continue
   105  		}
   106  		commitsString := match[2][1:]
   107  		commits := strings.Split(commitsString, ",")
   108  		// Checking out a branch, possibly at a specific commit
   109  		if len(commits) == 1 {
   110  			repos = append(repos, Repo{
   111  				Name:   thisRepo,
   112  				Branch: commits[0],
   113  				Pull:   "",
   114  			})
   115  			continue
   116  		}
   117  		// Checking out one or more PRs
   118  		repos = append(repos, Repo{
   119  			Name:   thisRepo,
   120  			Branch: "",
   121  			Pull:   commitsString,
   122  		})
   123  	}
   124  	return repos, nil
   125  }