10 "github.com/blang/semver"
11 "github.com/zyedidia/micro/internal/config"
12 git "gopkg.in/src-d/go-git.v4"
16 ErrMissingName = errors.New("Missing or empty name field")
17 ErrMissingDesc = errors.New("Missing or empty description field")
18 ErrMissingSite = errors.New("Missing or empty website field")
19 ErrMissingRepo = errors.New("Missing or empty repository field")
20 ErrMissingVersions = errors.New("Missing or empty versions field")
21 ErrMissingTag = errors.New("Missing or empty tag field")
22 ErrMissingRequire = errors.New("Missing or empty require field")
26 infojson = "plugin.json"
27 versionfile = "version.lock"
34 version semver.Version // currently installed version
37 func (p *Plugin) GetRequires() *PluginVersion {
38 for _, v := range p.info.Versions {
39 if p.version.Equals(v.Vers) {
46 // PluginVersion describes a version for a plugin as well as any dependencies that
48 // This marks a tag that corresponds to the version in the git repo
49 type PluginVersion struct {
51 Vstr string `json:"version"`
52 Tag string `json:"tag"`
53 Require map[string]string `json:"require"`
56 // PluginInfo contains all the needed info about a plugin
57 type PluginInfo struct {
58 Name string `json:"name"`
59 Desc string `json:"description"`
60 Site string `json:"website"`
61 Repo string `json:"repository"`
62 Versions []PluginVersion `json:"versions"`
65 // NewPluginInfo parses a JSON input into a valid PluginInfo struct
66 // Returns an error if there are any missing fields or any invalid fields
67 // There are no optional fields in a plugin info json file
68 func NewPluginInfo(data []byte) (*PluginInfo, error) {
71 dec := json.NewDecoder(bytes.NewReader(data))
72 dec.DisallowUnknownFields() // Force errors
74 if err := dec.Decode(&info); err != nil {
78 if len(info.Name) == 0 {
79 return nil, ErrMissingName
80 } else if len(info.Desc) == 0 {
81 return nil, ErrMissingDesc
82 } else if len(info.Site) == 0 {
83 return nil, ErrMissingSite
84 } else if len(info.Repo) == 0 {
85 return nil, ErrMissingRepo
86 } else if err := info.makeVersions(); err != nil {
93 func (i *PluginInfo) makeVersions() error {
94 if len(i.Versions) == 0 {
95 return ErrMissingVersions
98 for _, v := range i.Versions {
99 sv, err := semver.Make(v.Vstr)
106 } else if v.Require == nil {
107 return ErrMissingRequire
114 // ListInstalledPlugins searches the config directory for all installed plugins
115 // and returns the list of plugin infos corresponding to them
116 func ListInstalledPlugins() ([]*Plugin, error) {
117 pdir := path.Join(config.ConfigDir, "plugin")
119 files, err := ioutil.ReadDir(pdir)
124 var plugins []*Plugin
126 for _, dir := range files {
128 files, err := ioutil.ReadDir(path.Join(pdir, dir.Name()))
133 for _, f := range files {
134 if f.Name() == infojson {
135 dat, err := ioutil.ReadFile(path.Join(pdir, dir.Name(), infojson))
139 info, err := NewPluginInfo(dat)
144 versiondat, err := ioutil.ReadFile(path.Join(pdir, dir.Name(), versionfile))
148 sv, err := semver.Make(string(versiondat))
153 dirname := path.Join(pdir, dir.Name())
154 r, err := git.PlainOpen(dirname)
166 plugins = append(plugins, p)