github.com/StackExchange/blackbox/v2@v2.0.1-0.20220331193400-d84e904973ab/pkg/vcs/vcs.go (about)

     1  package vcs
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/StackExchange/blackbox/v2/models"
    11  )
    12  
    13  // Vcs is the handle
    14  type Vcs interface {
    15  	models.Vcs
    16  }
    17  
    18  // NewFnSig function signature needed by reg.
    19  type NewFnSig func() (Vcs, error)
    20  
    21  // Item stores one item
    22  type Item struct {
    23  	Name     string
    24  	New      NewFnSig
    25  	Priority int
    26  }
    27  
    28  // Catalog is the list of registered vcs's.
    29  var Catalog []*Item
    30  
    31  // Discover polls the VCS plug-ins to determine the VCS of directory.
    32  // The first to succeed is returned.
    33  // It never returns nil, since "NONE" is always valid.
    34  func Discover() (Vcs, string) {
    35  	for _, v := range Catalog {
    36  		h, err := v.New()
    37  		if err != nil {
    38  			return nil, "" // No idea how that would happen.
    39  		}
    40  		if b, repodir := h.Discover(); b {
    41  
    42  			// Try to find the rel path from CWD to RepoBase
    43  			wd, err := os.Getwd()
    44  			if err != nil {
    45  				fmt.Printf("ERROR: Can not determine cwd! Failing!\n")
    46  				os.Exit(1)
    47  			}
    48  			//fmt.Printf("DISCCOVER: WD=%q REPO=%q\n", wd, repodir)
    49  			if repodir != wd && strings.HasSuffix(repodir, wd) {
    50  				// This is a terrible hack.  We're basically guessing
    51  				// at the filesystem layout.  That said, it works on macOS.
    52  				// TODO(tlim): Abstract this out into a separate function
    53  				// so we can do integration tests on it (to know if it fails on
    54  				// a particular operating system.)
    55  				repodir = wd
    56  			}
    57  			r, err := filepath.Rel(wd, repodir)
    58  			if err != nil {
    59  				// Wait, we're not relative to each other? Give up and
    60  				// just return the abs repodir.
    61  				return h, repodir
    62  			}
    63  			return h, r
    64  		}
    65  	}
    66  	// This can't happen. If it does, we'll panic and that's ok.
    67  	return nil, ""
    68  }
    69  
    70  // Register a new VCS.
    71  func Register(name string, priority int, newfn NewFnSig) {
    72  	//fmt.Printf("VCS registered: %v\n", name)
    73  	item := &Item{
    74  		Name:     name,
    75  		New:      newfn,
    76  		Priority: priority,
    77  	}
    78  	Catalog = append(Catalog, item)
    79  
    80  	// Keep the list sorted.
    81  	sort.Slice(Catalog, func(i, j int) bool { return Catalog[j].Priority < Catalog[i].Priority })
    82  }