Skip to content

Commit

Permalink
load plugins at \use-plugin time
Browse files Browse the repository at this point in the history
this doesn't work. golang/go#20481 seems related.

Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
  • Loading branch information
vito committed Apr 18, 2019
1 parent 8b6f9b6 commit acae324
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 67 deletions.
10 changes: 5 additions & 5 deletions baselit/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func init() {
booklit.RegisterPlugin("base", NewPlugin)
booklit.RegisterPlugin("github.com/vito/booklit/baselit", NewPlugin)
}

func NewPlugin(section *booklit.Section) booklit.Plugin {
Expand All @@ -22,10 +22,10 @@ type Plugin struct {
section *booklit.Section
}

func (plugin Plugin) UsePlugin(name string) error {
pluginFactory, found := booklit.LookupPlugin(name)
if !found {
return fmt.Errorf("unknown plugin '%s'", name)
func (plugin Plugin) UsePlugin(importPath string) error {
pluginFactory, err := plugin.section.Processor.LoadPlugin(importPath)
if err != nil {
return err
}

plugin.section.UsePlugin(pluginFactory)
Expand Down
50 changes: 0 additions & 50 deletions booklitcmd/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ package booklitcmd

import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"plugin"

"github.com/sirupsen/logrus"
"github.com/vito/booklit"
Expand All @@ -29,8 +25,6 @@ type Command struct {

ServerPort int `long:"serve" short:"s" description:"Start an HTTP server on the given port."`

Plugins []string `long:"plugin" short:"p" description:"Package to import, providing a plugin."`

Debug bool `long:"debug" short:"d" description:"Log at debug level."`

AllowBrokenReferences bool `long:"allow-broken-references" description:"Replace broken references with a bogus tag."`
Expand All @@ -50,11 +44,6 @@ func (cmd *Command) Execute(args []string) error {
logrus.SetLevel(logrus.DebugLevel)
}

err := cmd.loadPlugins()
if err != nil {
return err
}

if cmd.ServerPort != 0 {
return cmd.Serve()
} else {
Expand Down Expand Up @@ -159,42 +148,3 @@ func (cmd *Command) Build() error {

return nil
}

func (cmd *Command) loadPlugins() error {
tmpdir, err := ioutil.TempDir("", "booklit-reexec")
if err != nil {
return err
}

defer func() {
_ = os.RemoveAll(tmpdir)
}()

for i, p := range cmd.Plugins {
log := logrus.WithFields(logrus.Fields{
"plugin": p,
})

pluginPath := filepath.Join(tmpdir, fmt.Sprintf("plugin-%d.so", i))

build := exec.Command("go", "build", "-buildmode=plugin", "-o", pluginPath, p)
build.Env = append(os.Environ(), "GOBIN="+tmpdir)
buildOutput, err := build.CombinedOutput()
if err != nil {
if _, ok := err.(*exec.ExitError); ok {
return fmt.Errorf("failed to compile plugin '%s':\n\n%s", p, string(buildOutput))
} else {
return err
}
}

_, err = plugin.Open(pluginPath)
if err != nil {
return fmt.Errorf("failed to load plugin '%s': %s", p, err)
}

log.Info("loaded plugin")
}

return nil
}
2 changes: 1 addition & 1 deletion booklitdoc/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

func init() {
booklit.RegisterPlugin("booklitdoc", NewPlugin)
booklit.RegisterPlugin("github.com/vito/booklit/booklitdoc", NewPlugin)

styles.Fallback = chroma.MustNewStyle("booklitdoc", chroma.StyleEntries{
chroma.Comment: "italic",
Expand Down
2 changes: 1 addition & 1 deletion chroma/plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import (
)

func init() {
booklit.RegisterPlugin("chroma", chroma.NewPlugin)
booklit.RegisterPlugin("github.com/vito/booklit/chroma/plugin", chroma.NewPlugin)
}
4 changes: 2 additions & 2 deletions docs/lit/baselit.lit
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
\use-plugin{booklitdoc}
\use-plugin{chroma}
\use-plugin{github.com/vito/booklit/booklitdoc}
\use-plugin{github.com/vito/booklit/chroma/plugin}

\title{The \code{baselit} Plugin}{baselit}

Expand Down
2 changes: 1 addition & 1 deletion docs/lit/getting-started.lit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\use-plugin{chroma}
\use-plugin{github.com/vito/booklit/chroma/plugin}

\title{Getting Started}

Expand Down
4 changes: 2 additions & 2 deletions docs/lit/html-renderer.lit
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
\use-plugin{booklitdoc}
\use-plugin{chroma}
\use-plugin{github.com/vito/booklit/booklitdoc}
\use-plugin{github.com/vito/booklit/chroma/plugin}

\title{The HTML Renderer}{html-renderer}

Expand Down
4 changes: 2 additions & 2 deletions docs/lit/plugins.lit
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
\use-plugin{booklitdoc}
\use-plugin{chroma}
\use-plugin{github.com/vito/booklit/booklitdoc}
\use-plugin{github.com/vito/booklit/chroma/plugin}

\title{Extending with Plugins}{plugins}

Expand Down
2 changes: 1 addition & 1 deletion docs/lit/syntax.lit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\use-plugin{chroma}
\use-plugin{github.com/vito/booklit/chroma/plugin}

\title{Document Syntax}{syntax}

Expand Down
58 changes: 58 additions & 0 deletions load/processor.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package load

import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"plugin"
"sync"
"time"

Expand All @@ -17,6 +22,9 @@ type Processor struct {

parsed map[string]parsedNode
parsedL sync.Mutex

loadedPlugins map[string]booklit.PluginFactory
loadedPluginsL sync.Mutex
}

type parsedNode struct {
Expand Down Expand Up @@ -125,6 +133,56 @@ func (processor *Processor) EvaluateNode(parent *booklit.Section, node ast.Node,
return section, nil
}

func (processor *Processor) LoadPlugin(importPath string) (booklit.PluginFactory, error) {
processor.loadedPluginsL.Lock()
defer processor.loadedPluginsL.Unlock()

if processor.loadedPlugins == nil {
processor.loadedPlugins = map[string]booklit.PluginFactory{}
}

pf, found := processor.loadedPlugins[importPath]
if found {
return pf, nil
}

tmpdir, err := ioutil.TempDir("", "booklit-load-plugin")
if err != nil {
return nil, err
}

defer func() {
_ = os.RemoveAll(tmpdir)
}()

pluginPath := filepath.Join(tmpdir, "plugin.so")

build := exec.Command("go", "build", "-buildmode=plugin", "-o", pluginPath, importPath)
build.Env = append(os.Environ(), "GOBIN="+tmpdir)
buildOutput, err := build.CombinedOutput()
if err != nil {
if _, ok := err.(*exec.ExitError); ok {
return nil, fmt.Errorf("failed to compile plugin '%s':\n\n%s", importPath, string(buildOutput))
} else {
return nil, err
}
}

_, err = plugin.Open(pluginPath)
if err != nil {
return nil, fmt.Errorf("failed to open plugin '%s': %s", importPath, err)
}

pf, found = booklit.LookupPlugin(importPath)
if !found {
return nil, fmt.Errorf("plugin loaded but did not register as '%s'", importPath)
}

processor.loadedPlugins[importPath] = pf

return pf, nil
}

func (processor *Processor) evaluateSection(section *booklit.Section, node ast.Node, pluginFactories []booklit.PluginFactory) error {
for _, pf := range pluginFactories {
section.UsePlugin(pf)
Expand Down
2 changes: 0 additions & 2 deletions scripts/build-docs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ go run cmd/booklit/*.go \
-i docs/lit/index.lit \
-o docs \
--html-templates docs/lit/html \
--plugin github.com/vito/booklit/booklitdoc \
--plugin github.com/vito/booklit/chroma/plugin \
"$@"
1 change: 1 addition & 0 deletions section.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Section struct {
type Partials map[string]Content

type SectionProcessor interface {
LoadPlugin(importPath string) (PluginFactory, error)
EvaluateFile(*Section, string, []PluginFactory) (*Section, error)
EvaluateNode(*Section, ast.Node, []PluginFactory) (*Section, error)
}
Expand Down

0 comments on commit acae324

Please sign in to comment.