github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/util/configv3/plugins_config.go (about) 1 package configv3 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "sort" 10 "strings" 11 12 "github.com/liamawhite/cli-with-i18n/util" 13 ) 14 15 // PluginsConfig represents the plugin configuration 16 type PluginsConfig struct { 17 Plugins map[string]Plugin `json:"Plugins"` 18 } 19 20 // Plugin represents the plugin as a whole, not be confused with PluginCommand 21 type Plugin struct { 22 Name string 23 Location string `json:"Location"` 24 Version PluginVersion `json:"Version"` 25 Commands []PluginCommand `json:"Commands"` 26 } 27 28 // PluginVersion is the plugin version information 29 type PluginVersion struct { 30 Major int `json:"Major"` 31 Minor int `json:"Minor"` 32 Build int `json:"Build"` 33 } 34 35 // String returns the plugin's version in the format x.y.z. 36 func (v PluginVersion) String() string { 37 if v.Major == 0 && v.Minor == 0 && v.Build == 0 { 38 return "N/A" 39 } 40 return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Build) 41 } 42 43 // PluginCommand represents an individual command inside a plugin 44 type PluginCommand struct { 45 Name string `json:"Name"` 46 Alias string `json:"Alias"` 47 HelpText string `json:"HelpText"` 48 UsageDetails PluginUsageDetails `json:"UsageDetails"` 49 } 50 51 // PluginUsageDetails contains the usage metadata provided by the plugin 52 type PluginUsageDetails struct { 53 Usage string `json:"Usage"` 54 Options map[string]string `json:"Options"` 55 } 56 57 // Plugins returns installed plugins from the config sorted by name (case-insensitive). 58 func (config *Config) Plugins() []Plugin { 59 plugins := []Plugin{} 60 for _, plugin := range config.pluginsConfig.Plugins { 61 plugins = append(plugins, plugin) 62 } 63 sort.Slice(plugins, func(i, j int) bool { 64 return strings.ToLower(plugins[i].Name) < strings.ToLower(plugins[j].Name) 65 }) 66 return plugins 67 } 68 69 // CalculateSHA1 returns the sha1 value of the plugin executable. If an error 70 // is encountered calculating sha1, N/A is returned 71 func (p Plugin) CalculateSHA1() string { 72 fileSHA, err := util.NewSha1Checksum(p.Location).ComputeFileSha1() 73 74 if err != nil { 75 return "N/A" 76 } 77 78 return fmt.Sprintf("%x", fileSHA) 79 } 80 81 // PluginCommands returns the plugin's commands sorted by command name. 82 func (p Plugin) PluginCommands() []PluginCommand { 83 sort.Slice(p.Commands, func(i, j int) bool { 84 return strings.ToLower(p.Commands[i].Name) < strings.ToLower(p.Commands[j].Name) 85 }) 86 return p.Commands 87 } 88 89 // CommandName returns the name of the plugin. The name is concatenated with 90 // alias if alias is specified. 91 func (c PluginCommand) CommandName() string { 92 if c.Name != "" && c.Alias != "" { 93 return fmt.Sprintf("%s, %s", c.Name, c.Alias) 94 } 95 return c.Name 96 } 97 98 // PluginHome returns the plugin configuration directory to: 99 // 1. The $CF_PLUGIN_HOME/.cf/plugins environment variable if set 100 // 2. Defaults to the home directory (outlined in LoadConfig)/.cf/plugins 101 func (config *Config) PluginHome() string { 102 if config.ENV.CFPluginHome != "" { 103 return filepath.Join(config.ENV.CFPluginHome, ".cf", "plugins") 104 } 105 106 return filepath.Join(homeDirectory(), ".cf", "plugins") 107 } 108 109 // AddPlugin adds the specified plugin to PluginsConfig 110 func (config *Config) AddPlugin(plugin Plugin) { 111 config.pluginsConfig.Plugins[plugin.Name] = plugin 112 } 113 114 // RemovePlugin removes the specified plugin from PluginsConfig idempotently 115 func (config *Config) RemovePlugin(pluginName string) { 116 delete(config.pluginsConfig.Plugins, pluginName) 117 } 118 119 // GetPlugin returns the requested plugin and true if it exists. 120 func (config *Config) GetPlugin(pluginName string) (Plugin, bool) { 121 plugin, exists := config.pluginsConfig.Plugins[pluginName] 122 return plugin, exists 123 } 124 125 // GetPluginCaseInsensitive finds the first matching plugin name case 126 // insensitive and returns true if it exists. 127 func (config *Config) GetPluginCaseInsensitive(pluginName string) (Plugin, bool) { 128 for name, plugin := range config.pluginsConfig.Plugins { 129 if strings.ToLower(name) == strings.ToLower(pluginName) { 130 return plugin, true 131 } 132 } 133 134 return Plugin{}, false 135 } 136 137 // WritePluginConfig writes the plugin config to config.json in the plugin home 138 // directory. 139 func (config *Config) WritePluginConfig() error { 140 // Marshal JSON 141 rawConfig, err := json.MarshalIndent(config.pluginsConfig, "", " ") 142 if err != nil { 143 return err 144 } 145 146 pluginFileDir := filepath.Join(config.PluginHome()) 147 err = os.MkdirAll(pluginFileDir, 0700) 148 if err != nil { 149 return err 150 } 151 152 // Write to file 153 return ioutil.WriteFile(filepath.Join(pluginFileDir, "config.json"), rawConfig, 0600) 154 }