Skip to content
This repository has been archived by the owner on Feb 16, 2024. It is now read-only.

Commit

Permalink
Added module support, and available Astilectron and Electron (#204)
Browse files Browse the repository at this point in the history
* Added module support, and available Astilectron and Electron

* PR cleanup, removed

* updated readme showing customizations for astilectron and electron versions
  • Loading branch information
alexj212 authored and asticode committed Oct 30, 2019
1 parent d400ccc commit 17a9797
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 54 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ var a, _ = astilectron.New(astilectron.Options{
AppIconDefaultPath: "<your .png icon>", // If path is relative, it must be relative to the data directory
AppIconDarwinPath: "<your .icns icon>", // Same here
BaseDirectoryPath: "<where you want the provisioner to install the dependencies>",
VersionAstilectron: "<version of Astilectron to utilize such as `0.33.0`>",
VersionElectron: "<version of Electron to utilize such as `4.0.1` | `6.1.2`>",
})
defer a.Close()

Expand Down
37 changes: 23 additions & 14 deletions astilectron.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import (

// Versions
const (
DefaultAcceptTCPTimeout = 30 * time.Second
VersionAstilectron = "0.33.0"
VersionElectron = "4.0.1"
DefaultAcceptTCPTimeout = 30 * time.Second
DefaultVersionAstilectron = "0.33.0"
DefaultVersionElectron = "4.0.1"
)

// Misc vars
Expand Down Expand Up @@ -68,16 +68,18 @@ type Astilectron struct {

// Options represents Astilectron options
type Options struct {
AcceptTCPTimeout time.Duration
AppName string
AppIconDarwinPath string // Darwin systems requires a specific .icns file
AppIconDefaultPath string
BaseDirectoryPath string
DataDirectoryPath string
ElectronSwitches []string
SingleInstance bool
SkipSetup bool // If true, the user must handle provisioning and executing astilectron.
TCPPort *int // The port to listen on.
AcceptTCPTimeout time.Duration
AppName string
AppIconDarwinPath string // Darwin systems requires a specific .icns file
AppIconDefaultPath string
BaseDirectoryPath string
DataDirectoryPath string
ElectronSwitches []string
SingleInstance bool
SkipSetup bool // If true, the user must handle provisioning and executing astilectron.
TCPPort *int // The port to listen on.
VersionAstilectron string
VersionElectron string
}

// Supported represents Astilectron supported features
Expand All @@ -93,6 +95,13 @@ func New(o Options) (a *Astilectron, err error) {
return
}

if o.VersionAstilectron == "" {
o.VersionAstilectron = DefaultVersionAstilectron
}
if o.VersionElectron == "" {
o.VersionElectron = DefaultVersionElectron
}

// Init
a = &Astilectron{
canceller: asticontext.NewCanceller(),
Expand Down Expand Up @@ -191,7 +200,7 @@ func (a *Astilectron) Start() (err error) {
func (a *Astilectron) provision() error {
astilog.Debug("Provisioning...")
var ctx, _ = a.canceller.NewContext()
return a.provisioner.Provision(ctx, a.options.AppName, runtime.GOOS, runtime.GOARCH, *a.paths)
return a.provisioner.Provision(ctx, a.options.AppName, runtime.GOOS, runtime.GOARCH, a.options.VersionAstilectron, a.options.VersionElectron, *a.paths)
}

// listenTCP creates a TCP server for astilectron to connect to
Expand Down
19 changes: 10 additions & 9 deletions paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Paths struct {

// newPaths creates new paths
func newPaths(os, arch string, o Options) (p *Paths, err error) {

// Init base directory path
p = &Paths{}
if err = p.initBaseDirectory(o.BaseDirectoryPath); err != nil {
Expand Down Expand Up @@ -58,12 +59,12 @@ func newPaths(os, arch string, o Options) (p *Paths, err error) {
p.provisionStatus = filepath.Join(p.vendorDirectory, "status.json")
p.astilectronDirectory = filepath.Join(p.vendorDirectory, "astilectron")
p.astilectronApplication = filepath.Join(p.astilectronDirectory, "main.js")
p.astilectronDownloadSrc = AstilectronDownloadSrc()
p.astilectronDownloadDst = filepath.Join(p.vendorDirectory, fmt.Sprintf("astilectron-v%s.zip", VersionAstilectron))
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, fmt.Sprintf("astilectron-%s", VersionAstilectron))
p.astilectronDownloadSrc = AstilectronDownloadSrc(o.VersionAstilectron)
p.astilectronDownloadDst = filepath.Join(p.vendorDirectory, fmt.Sprintf("astilectron-v%s.zip", o.VersionAstilectron))
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, fmt.Sprintf("astilectron-%s", o.VersionAstilectron))
p.electronDirectory = filepath.Join(p.vendorDirectory, fmt.Sprintf("electron-%s-%s", os, arch))
p.electronDownloadSrc = ElectronDownloadSrc(os, arch)
p.electronDownloadDst = filepath.Join(p.vendorDirectory, fmt.Sprintf("electron-%s-%s-v%s.zip", os, arch, VersionElectron))
p.electronDownloadSrc = ElectronDownloadSrc(os, arch, o.VersionElectron)
p.electronDownloadDst = filepath.Join(p.vendorDirectory, fmt.Sprintf("electron-%s-%s-v%s.zip", os, arch, o.VersionElectron))
p.electronUnzipSrc = p.electronDownloadDst
p.initAppExecutable(os, o.AppName)
return
Expand Down Expand Up @@ -114,12 +115,12 @@ func (p *Paths) initDataDirectory(dataDirectoryPath, appName string) (err error)
}

// AstilectronDownloadSrc returns the download URL of the (currently platform-independent) astilectron zip file
func AstilectronDownloadSrc() string {
return fmt.Sprintf("https://github.com/asticode/astilectron/archive/v%s.zip", VersionAstilectron)
func AstilectronDownloadSrc(versionAstilectron string) string {
return fmt.Sprintf("https://github.com/asticode/astilectron/archive/v%s.zip", versionAstilectron)
}

// ElectronDownloadSrc returns the download URL of the platform-dependant electron zipfile
func ElectronDownloadSrc(os, arch string) string {
func ElectronDownloadSrc(os, arch, versionElectron string) string {
// Get OS name
var o string
switch strings.ToLower(os) {
Expand All @@ -140,7 +141,7 @@ func ElectronDownloadSrc(os, arch string) string {
}

// Return url
return fmt.Sprintf("https://github.com/electron/electron/releases/download/v%s/electron-v%s-%s-%s.zip", VersionElectron, VersionElectron, o, a)
return fmt.Sprintf("https://github.com/electron/electron/releases/download/v%s/electron-v%s-%s-%s.zip", versionElectron, versionElectron, o, a)
}

// initAppExecutable initializes the app executable path
Expand Down
19 changes: 12 additions & 7 deletions paths_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ import (

func TestPaths(t *testing.T) {
const k = "APPDATA"
const VersionAstilectron = DefaultVersionAstilectron
const VersionElectron = DefaultVersionElectron

ad := os.Getenv(k)
os.Setenv(k, "")
ep, err := os.Executable()
ep = filepath.Dir(ep)
assert.NoError(t, err)
p, err := newPaths("linux", "amd64", Options{})

o := Options{VersionAstilectron: DefaultVersionAstilectron, VersionElectron: DefaultVersionElectron}
p, err := newPaths("linux", "amd64", o)
assert.NoError(t, err)
assert.Equal(t, ep+"/vendor/electron-linux-amd64/electron", p.AppExecutable())
assert.Equal(t, "", p.AppIconDarwinSrc())
Expand All @@ -34,35 +39,35 @@ func TestPaths(t *testing.T) {
assert.Equal(t, ep+"/vendor/electron-linux-amd64-v"+VersionElectron+".zip", p.ElectronUnzipSrc())
assert.Equal(t, ep+"/vendor/status.json", p.ProvisionStatus())
assert.Equal(t, ep+"/vendor", p.VendorDirectory())
p, err = newPaths("linux", "", Options{})
p, err = newPaths("linux", "", o)
assert.NoError(t, err)
assert.Equal(t, "https://github.com/electron/electron/releases/download/v"+VersionElectron+"/electron-v"+VersionElectron+"-linux-ia32.zip", p.ElectronDownloadSrc())
p, err = newPaths("linux", "arm", Options{})
p, err = newPaths("linux", "arm", o)
assert.NoError(t, err)
assert.Equal(t, "https://github.com/electron/electron/releases/download/v"+VersionElectron+"/electron-v"+VersionElectron+"-linux-armv7l.zip", p.ElectronDownloadSrc())
p, err = newPaths("darwin", "", Options{BaseDirectoryPath: "/path/to/base/directory", AppIconDarwinPath: "/path/to/darwin/icon", AppIconDefaultPath: "icon"})
p, err = newPaths("darwin", "", Options{BaseDirectoryPath: "/path/to/base/directory", AppIconDarwinPath: "/path/to/darwin/icon", AppIconDefaultPath: "icon", VersionAstilectron: DefaultVersionAstilectron, VersionElectron: DefaultVersionElectron})
assert.NoError(t, err)
assert.Equal(t, "/path/to/base/directory/vendor/electron-darwin-/Electron.app/Contents/MacOS/Electron", p.AppExecutable())
assert.Equal(t, "/path/to/darwin/icon", p.AppIconDarwinSrc())
assert.Equal(t, "/path/to/base/directory/icon", p.AppIconDefaultSrc())
assert.Equal(t, "https://github.com/electron/electron/releases/download/v"+VersionElectron+"/electron-v"+VersionElectron+"-darwin-x64.zip", p.ElectronDownloadSrc())
p, err = newPaths("darwin", "amd64", Options{AppName: "Test app", BaseDirectoryPath: "/path/to/base/directory", DataDirectoryPath: "/path/to/data/directory"})
p, err = newPaths("darwin", "amd64", Options{AppName: "Test app", BaseDirectoryPath: "/path/to/base/directory", DataDirectoryPath: "/path/to/data/directory", VersionAstilectron: DefaultVersionAstilectron, VersionElectron: DefaultVersionElectron})
assert.NoError(t, err)
assert.Equal(t, "/path/to/data/directory", p.DataDirectory())
assert.Equal(t, "/path/to/data/directory/vendor/electron-darwin-amd64/Test app.app/Contents/MacOS/Test app", p.AppExecutable())
assert.Equal(t, "/path/to/data/directory/vendor/electron-darwin-amd64-v"+VersionElectron+".zip", p.ElectronDownloadDst())
assert.Equal(t, "/path/to/data/directory/vendor/electron-darwin-amd64-v"+VersionElectron+".zip", p.ElectronUnzipSrc())
const pad = "/path/to/appdata"
os.Setenv(k, pad)
p, err = newPaths("windows", "amd64", Options{})
p, err = newPaths("windows", "amd64", o)
assert.NoError(t, err)
assert.Equal(t, pad, p.DataDirectory())
assert.Equal(t, pad+"/vendor", p.VendorDirectory())
assert.Equal(t, pad+"/vendor/electron-windows-amd64/electron.exe", p.AppExecutable())
assert.Equal(t, "https://github.com/electron/electron/releases/download/v"+VersionElectron+"/electron-v"+VersionElectron+"-win32-x64.zip", p.ElectronDownloadSrc())
assert.Equal(t, pad+"/vendor/electron-windows-amd64-v"+VersionElectron+".zip", p.ElectronDownloadDst())
assert.Equal(t, pad+"/vendor/electron-windows-amd64-v"+VersionElectron+".zip", p.ElectronUnzipSrc())
p, err = newPaths("windows", "", Options{})
p, err = newPaths("windows", "", o)
assert.NoError(t, err)
assert.Equal(t, "https://github.com/electron/electron/releases/download/v"+VersionElectron+"/electron-v"+VersionElectron+"-win32-ia32.zip", p.ElectronDownloadSrc())
os.Setenv(k, ad)
Expand Down
20 changes: 10 additions & 10 deletions provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var (

// Provisioner represents an object capable of provisioning Astilectron
type Provisioner interface {
Provision(ctx context.Context, appName, os, arch string, p Paths) error
Provision(ctx context.Context, appName, os, arch, versionAstilectron, versionElectron string, p Paths) error
}

// mover is a function that moves a package
Expand Down Expand Up @@ -59,7 +59,7 @@ func provisionStatusElectronKey(os, arch string) string {

// Provision implements the provisioner interface
// TODO Package app using electron instead of downloading Electron + Astilectron separately
func (p *defaultProvisioner) Provision(ctx context.Context, appName, os, arch string, paths Paths) (err error) {
func (p *defaultProvisioner) Provision(ctx context.Context, appName, os, arch, versionAstilectron, versionElectron string, paths Paths) (err error) {
// Retrieve provision status
var s ProvisionStatus
if s, err = p.ProvisionStatus(paths); err != nil {
Expand All @@ -69,18 +69,18 @@ func (p *defaultProvisioner) Provision(ctx context.Context, appName, os, arch st
defer p.updateProvisionStatus(paths, &s)

// Provision astilectron
if err = p.provisionAstilectron(ctx, paths, s); err != nil {
if err = p.provisionAstilectron(ctx, paths, s, versionAstilectron); err != nil {
err = errors.Wrap(err, "provisioning astilectron failed")
return
}
s.Astilectron = &ProvisionStatusPackage{Version: VersionAstilectron}
s.Astilectron = &ProvisionStatusPackage{Version: versionAstilectron}

// Provision electron
if err = p.provisionElectron(ctx, paths, s, appName, os, arch); err != nil {
if err = p.provisionElectron(ctx, paths, s, appName, os, arch, versionElectron); err != nil {
err = errors.Wrap(err, "provisioning electron failed")
return
}
s.Electron[provisionStatusElectronKey(os, arch)] = &ProvisionStatusPackage{Version: VersionElectron}
s.Electron[provisionStatusElectronKey(os, arch)] = &ProvisionStatusPackage{Version: versionElectron}
return
}

Expand Down Expand Up @@ -143,13 +143,13 @@ func (p *defaultProvisioner) updateProvisionStatus(paths Paths, s *ProvisionStat
}

// provisionAstilectron provisions astilectron
func (p *defaultProvisioner) provisionAstilectron(ctx context.Context, paths Paths, s ProvisionStatus) error {
return p.provisionPackage(ctx, paths, s.Astilectron, p.moverAstilectron, "Astilectron", VersionAstilectron, paths.AstilectronUnzipSrc(), paths.AstilectronDirectory(), nil)
func (p *defaultProvisioner) provisionAstilectron(ctx context.Context, paths Paths, s ProvisionStatus, versionAstilectron string) error {
return p.provisionPackage(ctx, paths, s.Astilectron, p.moverAstilectron, "Astilectron", versionAstilectron, paths.AstilectronUnzipSrc(), paths.AstilectronDirectory(), nil)
}

// provisionElectron provisions electron
func (p *defaultProvisioner) provisionElectron(ctx context.Context, paths Paths, s ProvisionStatus, appName, os, arch string) error {
return p.provisionPackage(ctx, paths, s.Electron[provisionStatusElectronKey(os, arch)], p.moverElectron, "Electron", VersionElectron, paths.ElectronUnzipSrc(), paths.ElectronDirectory(), func() (err error) {
func (p *defaultProvisioner) provisionElectron(ctx context.Context, paths Paths, s ProvisionStatus, appName, os, arch, versionElectron string) error {
return p.provisionPackage(ctx, paths, s.Electron[provisionStatusElectronKey(os, arch)], p.moverElectron, "Electron", versionElectron, paths.ElectronUnzipSrc(), paths.ElectronDirectory(), func() (err error) {
switch os {
case "darwin":
if err = p.provisionElectronFinishDarwin(appName, paths); err != nil {
Expand Down
28 changes: 14 additions & 14 deletions provisioner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (
"github.com/stretchr/testify/assert"
)

func testProvisionerSuccessful(t *testing.T, p Paths, osName, arch string) {
func testProvisionerSuccessful(t *testing.T, p Paths, osName, arch, versionAstilectron, versionElectron string) {
_, err := os.Stat(p.AstilectronApplication())
assert.NoError(t, err)
_, err = os.Stat(p.AppExecutable())
assert.NoError(t, err)
b, err := ioutil.ReadFile(p.ProvisionStatus())
assert.NoError(t, err)
assert.Equal(t, "{\"astilectron\":{\"version\":\""+VersionAstilectron+"\"},\"electron\":{\""+provisionStatusElectronKey(osName, arch)+"\":{\"version\":\""+VersionElectron+"\"}}}\n", string(b))
assert.Equal(t, "{\"astilectron\":{\"version\":\""+versionAstilectron+"\"},\"electron\":{\""+provisionStatusElectronKey(osName, arch)+"\":{\"version\":\""+versionElectron+"\"}}}\n", string(b))
}

func TestDefaultProvisioner(t *testing.T) {
Expand All @@ -34,17 +34,17 @@ func TestDefaultProvisioner(t *testing.T) {
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, "astilectron")
p.astilectronDownloadSrc = s.URL + "/provisioner/astilectron"
p.electronDownloadSrc = s.URL + "/provisioner/electron/linux"
err = DefaultProvisioner.Provision(context.Background(), "", "linux", "amd64", *p)
err = DefaultProvisioner.Provision(context.Background(), "", "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "linux", "amd64")
testProvisionerSuccessful(t, *p, "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)

// Test nothing happens if provision status is up to date
mh.e = true
os.Remove(p.AstilectronDownloadDst())
os.Remove(p.ElectronDownloadDst())
err = DefaultProvisioner.Provision(context.Background(), "", "linux", "amd64", *p)
err = DefaultProvisioner.Provision(context.Background(), "", "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "linux", "amd64")
testProvisionerSuccessful(t, *p, "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)

// Test windows
mh.e = false
Expand All @@ -54,9 +54,9 @@ func TestDefaultProvisioner(t *testing.T) {
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, "astilectron")
p.astilectronDownloadSrc = s.URL + "/provisioner/astilectron"
p.electronDownloadSrc = s.URL + "/provisioner/electron/windows"
err = DefaultProvisioner.Provision(context.Background(), "", "windows", "amd64", *p)
err = DefaultProvisioner.Provision(context.Background(), "", "windows", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "windows", "amd64")
testProvisionerSuccessful(t, *p, "windows", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)

// Test darwin without custom app name + icon
os.RemoveAll(o.BaseDirectoryPath)
Expand All @@ -65,9 +65,9 @@ func TestDefaultProvisioner(t *testing.T) {
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, "astilectron")
p.astilectronDownloadSrc = s.URL + "/provisioner/astilectron"
p.electronDownloadSrc = s.URL + "/provisioner/electron/darwin"
err = DefaultProvisioner.Provision(context.Background(), "", "darwin", "amd64", *p)
err = DefaultProvisioner.Provision(context.Background(), "", "darwin", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "darwin", "amd64")
testProvisionerSuccessful(t, *p, "darwin", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)

// Test darwin with custom app name + icon
os.RemoveAll(o.BaseDirectoryPath)
Expand All @@ -80,9 +80,9 @@ func TestDefaultProvisioner(t *testing.T) {
p.astilectronUnzipSrc = filepath.Join(p.astilectronDownloadDst, "astilectron")
p.astilectronDownloadSrc = s.URL + "/provisioner/astilectron"
p.electronDownloadSrc = s.URL + "/provisioner/electron/darwin"
err = DefaultProvisioner.Provision(context.Background(), o.AppName, "darwin", "amd64", *p)
err = DefaultProvisioner.Provision(context.Background(), o.AppName, "darwin", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "darwin", "amd64")
testProvisionerSuccessful(t, *p, "darwin", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)
// Rename
_, err = os.Stat(filepath.Join(p.ElectronDirectory(), o.AppName+".app"))
assert.NoError(t, err)
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestNewDisembedderProvisioner(t *testing.T) {
pvb := NewDisembedderProvisioner(mockedDisembedder, "astilectron", "electron/linux")

// Test provision
err = pvb.Provision(context.Background(), "", "linux", "amd64", *p)
err = pvb.Provision(context.Background(), "", "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron, *p)
assert.NoError(t, err)
testProvisionerSuccessful(t, *p, "linux", "amd64")
testProvisionerSuccessful(t, *p, "linux", "amd64", DefaultVersionAstilectron, DefaultVersionElectron)
}

0 comments on commit 17a9797

Please sign in to comment.