github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/actor/pluginaction/plugin_info.go (about)

     1  package pluginaction
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  
     7  	"github.com/liamawhite/cli-with-i18n/util/configv3"
     8  	"github.com/liamawhite/cli-with-i18n/util/generic"
     9  )
    10  
    11  type PluginInfo struct {
    12  	Name     string
    13  	Version  string
    14  	URL      string
    15  	Checksum string
    16  }
    17  
    18  // FetchingPluginInfoFromRepositoryError is returned an error is encountered
    19  // getting plugin info from a repository
    20  type FetchingPluginInfoFromRepositoryError struct {
    21  	RepositoryName string
    22  	Err            error
    23  }
    24  
    25  func (e FetchingPluginInfoFromRepositoryError) Error() string {
    26  	return fmt.Sprintf("Plugin repository %s returned %s.", e.RepositoryName, e.Err.Error())
    27  }
    28  
    29  // NoCompatibleBinaryError is returned when a repository contains a specified
    30  // plugin but not for the specified platform
    31  type NoCompatibleBinaryError struct {
    32  }
    33  
    34  func (e NoCompatibleBinaryError) Error() string {
    35  	return "Plugin requested has no binary available for your platform."
    36  }
    37  
    38  // PluginNotFoundInRepositoryError is an error returned when a plugin is not found.
    39  type PluginNotFoundInRepositoryError struct {
    40  	PluginName     string
    41  	RepositoryName string
    42  }
    43  
    44  // Error outputs the plugin not found in repository error message.
    45  func (e PluginNotFoundInRepositoryError) Error() string {
    46  	return fmt.Sprintf("Plugin %s not found in repository %s", e.PluginName, e.RepositoryName)
    47  }
    48  
    49  // PluginNotFoundInAnyRepositoryError is an error returned when a plugin cannot
    50  // be found in any repositories.
    51  type PluginNotFoundInAnyRepositoryError struct {
    52  	PluginName string
    53  }
    54  
    55  // Error outputs that the plugin cannot be found in any repositories.
    56  func (e PluginNotFoundInAnyRepositoryError) Error() string {
    57  	return fmt.Sprintf("Plugin %s not found in any registered repo", e.PluginName)
    58  }
    59  
    60  // GetPluginInfoFromRepositoriesForPlatform returns the newest version of the specified plugin
    61  // and all the repositories that contain that version.
    62  func (actor Actor) GetPluginInfoFromRepositoriesForPlatform(pluginName string, pluginRepos []configv3.PluginRepository, platform string) (PluginInfo, []string, error) {
    63  	var reposWithPlugin []string
    64  	var newestPluginInfo PluginInfo
    65  	var pluginFoundWithIncompatibleBinary bool
    66  
    67  	for _, repo := range pluginRepos {
    68  		pluginInfo, err := actor.getPluginInfoFromRepositoryForPlatform(pluginName, repo, platform)
    69  		switch err.(type) {
    70  		case PluginNotFoundInRepositoryError:
    71  			continue
    72  		case NoCompatibleBinaryError:
    73  			pluginFoundWithIncompatibleBinary = true
    74  			continue
    75  		case nil:
    76  			if len(reposWithPlugin) == 0 || lessThan(newestPluginInfo.Version, pluginInfo.Version) {
    77  				newestPluginInfo = pluginInfo
    78  				reposWithPlugin = []string{repo.Name}
    79  			} else if pluginInfo.Version == newestPluginInfo.Version {
    80  				reposWithPlugin = append(reposWithPlugin, repo.Name)
    81  			}
    82  		default:
    83  			return PluginInfo{}, nil, FetchingPluginInfoFromRepositoryError{
    84  				RepositoryName: repo.Name,
    85  				Err:            err,
    86  			}
    87  		}
    88  	}
    89  
    90  	if len(reposWithPlugin) == 0 {
    91  		if pluginFoundWithIncompatibleBinary {
    92  			return PluginInfo{}, nil, NoCompatibleBinaryError{}
    93  		} else {
    94  			return PluginInfo{}, nil, PluginNotFoundInAnyRepositoryError{PluginName: pluginName}
    95  		}
    96  	}
    97  	return newestPluginInfo, reposWithPlugin, nil
    98  }
    99  
   100  // GetPlatformString exists solely for the purposes of mocking it out for command-layers tests.
   101  func (actor Actor) GetPlatformString(runtimeGOOS string, runtimeGOARCH string) string {
   102  	return generic.GeneratePlatform(runtime.GOOS, runtime.GOARCH)
   103  }
   104  
   105  // getPluginInfoFromRepositoryForPlatform returns the plugin info, if found, from
   106  // the specified repository for the specified platform.
   107  func (actor Actor) getPluginInfoFromRepositoryForPlatform(pluginName string, pluginRepo configv3.PluginRepository, platform string) (PluginInfo, error) {
   108  	pluginRepository, err := actor.client.GetPluginRepository(pluginRepo.URL)
   109  	if err != nil {
   110  		return PluginInfo{}, err
   111  	}
   112  
   113  	var pluginFoundWithIncompatibleBinary bool
   114  
   115  	for _, plugin := range pluginRepository.Plugins {
   116  		if plugin.Name == pluginName {
   117  			for _, pluginBinary := range plugin.Binaries {
   118  				if pluginBinary.Platform == platform {
   119  					return PluginInfo{Name: plugin.Name, Version: plugin.Version, URL: pluginBinary.URL, Checksum: pluginBinary.Checksum}, nil
   120  				}
   121  			}
   122  			pluginFoundWithIncompatibleBinary = true
   123  		}
   124  	}
   125  
   126  	if pluginFoundWithIncompatibleBinary {
   127  		return PluginInfo{}, NoCompatibleBinaryError{}
   128  	} else {
   129  		return PluginInfo{}, PluginNotFoundInRepositoryError{PluginName: pluginName, RepositoryName: pluginRepo.Name}
   130  	}
   131  }