Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions blueprint/zip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Package blueprint provides functions for packaging Enapter blueprints
// into zip archives, with support for .blueprintignore files.
package blueprint

import (
"archive/zip"
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/fs"
"strings"

"github.com/go-git/go-git/v5/plumbing/format/gitignore"
)

const ignoreFileName = ".blueprintignore"

// Zip creates a zip archive from the blueprint directory at the given
// filesystem root. It respects .blueprintignore patterns (gitignore syntax).
// The .blueprintignore file itself is excluded from the archive.
func Zip(fsys fs.FS) ([]byte, error) {
matcher, err := loadIgnoreMatcher(fsys)
if err != nil {
return nil, fmt.Errorf("load %s: %w", ignoreFileName, err)
}

buf := &bytes.Buffer{}
zw := zip.NewWriter(buf)

err = fs.WalkDir(fsys, ".", func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
}
if path == "." {
return nil
}

if matcher.Match(path, entry.IsDir()) {
if entry.IsDir() {
return fs.SkipDir
}
return nil
}

if entry.IsDir() {
return nil
}

f, err := fsys.Open(path)
if err != nil {
return fmt.Errorf("open: %w", err)
}
defer f.Close()

zf, err := zw.Create(path)
if err != nil {
return fmt.Errorf("create: %w", err)
}

if _, err = io.Copy(zf, f); err != nil {
return fmt.Errorf("copy: %w", err)
}
return nil
Comment thread
kulti marked this conversation as resolved.
})
if err != nil {
return nil, fmt.Errorf("walk dir: %w", err)
}

if err := zw.Close(); err != nil {
return nil, fmt.Errorf("close zip: %w", err)
}

return buf.Bytes(), nil
}

type ignoreMatcher struct {
m gitignore.Matcher
noFile bool
}

func (m *ignoreMatcher) Match(path string, isDir bool) bool {
if m.noFile {
return false
}

if path == ignoreFileName {
return true
}

parts := strings.Split(path, "/")
return m.m.Match(parts, isDir)
}

func loadIgnoreMatcher(fsys fs.FS) (*ignoreMatcher, error) {
f, err := fsys.Open(ignoreFileName)
if errors.Is(err, fs.ErrNotExist) {
return &ignoreMatcher{noFile: true}, nil
}
if err != nil {
return nil, err
}
defer f.Close()

var patterns []gitignore.Pattern

scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
patterns = append(patterns, gitignore.ParsePattern(line, nil))
}
if err := scanner.Err(); err != nil {
return nil, err
}

return &ignoreMatcher{m: gitignore.NewMatcher(patterns)}, nil
}
1 change: 0 additions & 1 deletion bp/firmware.lua

This file was deleted.

7 changes: 0 additions & 7 deletions bp/manifest.yml

This file was deleted.

17 changes: 17 additions & 0 deletions internal/app/cliflags/trim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cliflags

import (
"context"
"strings"

"github.com/urfave/cli/v3"
)

// TrimSpaceAction returns a cli.StringFlag Action that trims leading and
// trailing whitespace from the flag value and stores it in dest.
func TrimSpaceAction(dest *string) func(context.Context, *cli.Command, string) error {
return func(_ context.Context, _ *cli.Command, v string) error {
*dest = strings.TrimSpace(v)
return nil
}
}
4 changes: 3 additions & 1 deletion internal/app/enaptercli/cmd_blueprint_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"os"

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/blueprint"
)

type cmdBlueprintUpload struct {
Expand Down Expand Up @@ -82,7 +84,7 @@ func uploadBlueprint(

var data []byte
if fi.IsDir() {
data, err = zipDir(blueprintPath)
data, err = blueprint.Zip(os.DirFS(blueprintPath))
if err != nil {
return fmt.Errorf("zip blueprint directory: %w", err)
}
Expand Down
2 changes: 2 additions & 0 deletions internal/app/enaptercli/cmd_connection_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/internal/app/cliflags"
"github.com/enapter/enapter-cli/internal/app/configfile"
)

Expand All @@ -34,6 +35,7 @@ func buildCmdConnectionAdd() *cli.Command {
Usage: "Connection name",
Destination: &cmd.name,
Required: true,
Action: cliflags.TrimSpaceAction(&cmd.name),
},
&cli.BoolFlag{
Name: "gateway",
Expand Down
7 changes: 5 additions & 2 deletions internal/app/enaptercli/cmd_device_create_lua_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"errors"
"fmt"
"net/http"
"strings"

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/internal/app/cliflags"
)

type cmdDeviceCreateLua struct {
Expand Down Expand Up @@ -54,10 +55,12 @@ func (c *cmdDeviceCreateLua) Flags() []cli.Flag {
Usage: "name for the new Lua device",
Destination: &c.deviceName,
Required: true,
Action: cliflags.TrimSpaceAction(&c.deviceName),
}, &cli.StringFlag{
Name: "device-slug",
Usage: "slug for the new Lua device",
Destination: &c.deviceSlug,
Action: cliflags.TrimSpaceAction(&c.deviceSlug),
}, &cli.StringFlag{
Name: "blueprint-id",
Aliases: []string{"b"},
Expand Down Expand Up @@ -101,7 +104,7 @@ func (c *cmdDeviceCreateLua) do(ctx context.Context) error {

body, err := json.Marshal(map[string]interface{}{
"runtime_id": runtimeID,
"name": strings.TrimSpace(c.deviceName),
"name": c.deviceName,
"slug": c.deviceSlug,
"blueprint_id": c.blueprintID,
})
Expand Down
7 changes: 5 additions & 2 deletions internal/app/enaptercli/cmd_device_create_standalone.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/internal/app/cliflags"
)

type cmdDeviceCreateStandalone struct {
Expand Down Expand Up @@ -45,10 +46,12 @@ func (c *cmdDeviceCreateStandalone) Flags() []cli.Flag {
Usage: "Name for the new device",
Destination: &c.deviceName,
Required: true,
Action: cliflags.TrimSpaceAction(&c.deviceName),
}, &cli.StringFlag{
Name: "device-slug",
Usage: "Slug for the new standalone device",
Destination: &c.deviceSlug,
Action: cliflags.TrimSpaceAction(&c.deviceSlug),
})
}

Expand All @@ -60,7 +63,7 @@ func (c *cmdDeviceCreateStandalone) do(ctx context.Context) error {

body, err := json.Marshal(map[string]any{
"site_id": siteID,
"name": strings.TrimSpace(c.deviceName),
"name": c.deviceName,
"slug": c.deviceSlug,
})
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions internal/app/enaptercli/cmd_device_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/internal/app/cliflags"
)

type cmdDeviceUpdate struct {
Expand Down Expand Up @@ -46,18 +47,20 @@ func (c *cmdDeviceUpdate) Flags() []cli.Flag {
Name: "name",
Usage: "Device name",
Destination: &c.name,
Action: cliflags.TrimSpaceAction(&c.name),
},
&cli.StringFlag{
Name: "slug",
Usage: "Device slug",
Destination: &c.slug,
Action: cliflags.TrimSpaceAction(&c.slug),
},
)
}

func (c *cmdDeviceUpdate) do(ctx context.Context) error {
payload := map[string]string{
"name": strings.TrimSpace(c.name),
"name": c.name,
"slug": c.slug,
}
Comment thread
kulti marked this conversation as resolved.
body, err := json.Marshal(payload)
Expand Down
1 change: 1 addition & 0 deletions internal/app/enaptercli/cmd_rule_engine_rule_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func (c *cmdRuleEngineRuleCreate) Flags() []cli.Flag {
Usage: "Slug for the new rule",
Destination: &c.slug,
Required: true,
Action: cliflags.TrimSpaceAction(&c.slug),
},
&cli.StringFlag{
Name: "script",
Expand Down
3 changes: 3 additions & 0 deletions internal/app/enaptercli/cmd_rule_engine_rule_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"net/http"

"github.com/urfave/cli/v3"

"github.com/enapter/enapter-cli/internal/app/cliflags"
)

type cmdRuleEngineRuleUpdate struct {
Expand Down Expand Up @@ -42,6 +44,7 @@ func (c *cmdRuleEngineRuleUpdate) Flags() []cli.Flag {
Name: "slug",
Usage: "A new rule slug",
Destination: &c.slug,
Action: cliflags.TrimSpaceAction(&c.slug),
},
)
}
Expand Down
Loading
Loading