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
11 changes: 2 additions & 9 deletions pkg/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ func NewCore() *Core {
panic(err)
}

err = c.fs.MkdirAll(filesystem.DirName, 0o755)
if err != nil {
panic(err)
}

return &c
}

Expand Down Expand Up @@ -104,13 +99,11 @@ func (c *Core) resetCore() {

// Loads, if exists, or creates new repository with the given name.
func (c *Core) initCalendarRepo(name string) (*gogit.Repository, error) {
repoPath := c.fs.Join(filesystem.DirName, name)

if err := c.fs.MkdirAll(repoPath, 0o755); err != nil {
if err := c.fs.MkdirAll(name, 0o755); err != nil {
return nil, fmt.Errorf("create repo dir: %w", err)
}

repoFS, err := c.fs.Chroot(repoPath)
repoFS, err := c.fs.Chroot(name)
if err != nil {
return nil, fmt.Errorf("chroot repo dir: %w", err)
}
Expand Down
18 changes: 8 additions & 10 deletions pkg/core/core_calendars.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"strings"

"github.com/git-calendar/core/pkg/encryption"
"github.com/git-calendar/core/pkg/filesystem"
gogitutil "github.com/go-git/go-billy/v5/util"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
Expand All @@ -29,7 +28,7 @@ func (c *Core) CreateCalendar(name, password string) error {
if len(password) != 0 {
key = encryption.DeriveKey(password, []byte(name))

keyFile, err := c.fs.Create(c.fs.Join(filesystem.DirName, fmt.Sprintf("%s.key", name)))
keyFile, err := c.fs.Create(fmt.Sprintf("%s.key", name))
if err != nil {
return fmt.Errorf("failed to create key file: %w", err)
}
Expand Down Expand Up @@ -61,7 +60,7 @@ func (c *Core) LoadCalendars() error {
c.resetCore()

// load repositories
entries, err := c.fs.ReadDir(filesystem.DirName)
entries, err := c.fs.ReadDir(".")
if err != nil {
return fmt.Errorf("failed to list all directories in root: %w", err)
}
Expand All @@ -79,7 +78,7 @@ func (c *Core) LoadCalendars() error {
}

var key []byte = nil
keyFile, err := c.fs.Open(c.fs.Join(filesystem.DirName, fmt.Sprintf("%s.key", name)))
keyFile, err := c.fs.Open(fmt.Sprintf("%s.key", name))
if err == nil {
key, err = io.ReadAll(keyFile)
if err != nil {
Expand Down Expand Up @@ -147,11 +146,10 @@ func (c *Core) CloneCalendar(repoUrl url.URL, password string) error {
}

// make sure that the repo dir is created
repoPath := c.fs.Join(filesystem.DirName, calendarName)
if err := c.fs.MkdirAll(repoPath, 0o755); err != nil {
if err := c.fs.MkdirAll(calendarName, 0o755); err != nil {
return fmt.Errorf("create repo dir: %w", err)
}
repoFS, err := c.fs.Chroot(repoPath)
repoFS, err := c.fs.Chroot(calendarName)
if err != nil {
return fmt.Errorf("chroot repo dir: %w", err)
}
Expand Down Expand Up @@ -186,7 +184,7 @@ func (c *Core) CloneCalendar(repoUrl url.URL, password string) error {
if len(password) != 0 {
key = encryption.DeriveKey(password, []byte(calendarName))

keyFile, err := c.fs.Create(c.fs.Join(filesystem.DirName, fmt.Sprintf("%s.key", calendarName)))
keyFile, err := c.fs.Create(fmt.Sprintf("%s.key", calendarName))
if err != nil {
return fmt.Errorf("failed to create key file: %w", err)
}
Expand All @@ -211,12 +209,12 @@ func (c *Core) RemoveCalendar(name string) error {
delete(c.calendars, name)

// remove dir from filesystem
if err := gogitutil.RemoveAll(c.fs, c.fs.Join(filesystem.DirName, name)); err != nil {
if err := gogitutil.RemoveAll(c.fs, name); err != nil {
return fmt.Errorf("failed to remove repo directory: %w", err)
}

// try to remove encryption key
_ = c.fs.Remove(c.fs.Join(filesystem.DirName, fmt.Sprintf("%s.key", name)))
_ = c.fs.Remove(fmt.Sprintf("%s.key", name))

// TODO: This is the lazy way.
// LoadCalendars does full erase and load again for events map and tree. It also deletes all the repos, and reloads them from disk.
Expand Down
5 changes: 2 additions & 3 deletions pkg/core/core_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"slices"
"time"

"github.com/git-calendar/core/pkg/filesystem"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/google/uuid"
Expand Down Expand Up @@ -381,7 +380,7 @@ func (c *Core) saveAndCommitEvent(event *Event, commitMsg string) error {
}

// ensure events directory exists
dirPath := c.fs.Join(filesystem.DirName, event.Calendar, EventsDirName)
dirPath := c.fs.Join(event.Calendar, EventsDirName)
if err := c.fs.MkdirAll(dirPath, 0o755); err != nil {
return fmt.Errorf("failed mkdir events: %w", err)
}
Expand Down Expand Up @@ -437,7 +436,7 @@ func (c *Core) deleteAndCommitEvent(eventId uuid.UUID, commitMsg string) error {
filename := fmt.Sprintf("%s.json", eventId)

// -------- remove from disk --------
filePath := c.fs.Join(filesystem.DirName, event.Calendar, EventsDirName, filename)
filePath := c.fs.Join(event.Calendar, EventsDirName, filename)
if err := c.fs.Remove(filePath); err != nil {
// TODO maybe continue, to clean the git from this file
return fmt.Errorf("failed to remove file from disk: %w", err)
Expand Down
15 changes: 14 additions & 1 deletion pkg/filesystem/fs_classic.go → pkg/filesystem/classic.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ package filesystem

import (
"os"
"path/filepath"

"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/helper/chroot"
"github.com/go-git/go-billy/v5/osfs"
)

Expand All @@ -21,5 +23,16 @@ func GetFS() (billy.Filesystem, error) {
return nil, err
}

return osfs.New(home), nil
// ensure the directory exists on the real filesystem
rootPath := filepath.Join(home, DirName)
if err := os.MkdirAll(rootPath, 0o755); err != nil {
return nil, err
}

// base filesystem rooted at home
base := osfs.New(home)

// chroot into DirName
scoped := chroot.New(base, DirName)
return scoped, nil
}
38 changes: 38 additions & 0 deletions pkg/filesystem/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//go:build js && wasm

package filesystem

import (
"errors"
"fmt"
"syscall/js"

"github.com/git-calendar/core/pkg/opfs"
"github.com/go-git/go-billy/v5"
)

const DirName = "git-calendar-data"

func GetFS() (billy.Filesystem, error) {
// gets the handle from js window.opfsRootHandle
rootHandle := js.Global().Get("opfsRootHandle")
if rootHandle.IsUndefined() {
return nil, errors.New("opfsRootHandle not initialized")
}

// create OPFS rooted at /
fs := opfs.New(rootHandle)

// ensure directory exists
if err := fs.MkdirAll(DirName, 0o755); err != nil {
return nil, fmt.Errorf("failed to create dir: %w", err)
}

// chroot into the directory
chrooted, err := fs.Chroot(DirName)
if err != nil {
return nil, fmt.Errorf("failed to chroot: %w", err)
}

return chrooted, nil
}
4 changes: 2 additions & 2 deletions pkg/filesystem/fs_file_wasm.go → pkg/opfs/file.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//go:build js && wasm

package filesystem
package opfs

import (
"fmt"
Expand Down Expand Up @@ -214,7 +214,7 @@ func (f *OPFSFile) openAccess() error {

var err error
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createSyncAccessHandle
f.inode.access, err = await(f.inode.handle.Call("createSyncAccessHandle")) // returns Promise<FileSystemSyncAccessHandle>
f.inode.access, err = Await(f.inode.handle.Call("createSyncAccessHandle")) // returns Promise<FileSystemSyncAccessHandle>
return err
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//go:build js && wasm

package filesystem
package opfs

import (
"io/fs"
Expand Down
44 changes: 18 additions & 26 deletions pkg/filesystem/fs_wasm.go → pkg/opfs/fs.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//go:build js && wasm

package filesystem
package opfs

import (
"errors"
"fmt"
"io"
"io/fs"
Expand All @@ -19,27 +18,20 @@ import (
"github.com/go-git/go-billy/v5/helper/chroot"
)

const DirName = "git-calendar-data"

func GetFS() (billy.Filesystem, error) {
rootHandle := js.Global().Get("opfsRootHandle")
if rootHandle.IsUndefined() {
return nil, errors.New("opfsRootHandle not initialized")
}

return &OPFS{
root: rootHandle,
}, nil
}

// Origin private file system
//
// https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system
type OPFS struct {
root js.Value // FileSystemDirectoryHandle
RootHandle js.Value // FileSystemDirectoryHandle
}

var _ billy.Filesystem = (*OPFS)(nil) // makes sure that it implements all the interface methods, it wont compile without it
var _ billy.Filesystem = (*OPFS)(nil) // makes sure that it implements all the interface methods, it won't compile without it

func New(baseDirHandle js.Value) *OPFS {
return &OPFS{
RootHandle: baseDirHandle,
}
}

func (fs *OPFS) MkdirAll(path string, perm fs.FileMode) error {
// OPFS ignores permissions (perm)
Expand Down Expand Up @@ -93,7 +85,7 @@ func (fs *OPFS) OpenFile(fullPath string, flag int, perm os.FileMode) (billy.Fil
}

// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/getFileHandle
handle, err := await(dirHandle.Call("getFileHandle", fileName, map[string]any{"create": create})) // returns Promise<FileSystemFileHandle>
handle, err := Await(dirHandle.Call("getFileHandle", fileName, map[string]any{"create": create})) // returns Promise<FileSystemFileHandle>
if err != nil {
if strings.Contains(err.Error(), "NotFoundError") {
return nil, os.ErrNotExist
Expand Down Expand Up @@ -149,7 +141,7 @@ func (fs *OPFS) Remove(path string) error {
// OPFS FileSystemDirectoryHandle provides a native removeEntry method
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/removeEntry
// a non-empty directory will not be removed
_, err = await(dirHandle.Call("removeEntry", name))
_, err = Await(dirHandle.Call("removeEntry", name))
if err == nil {
return nil // removed ok
}
Expand Down Expand Up @@ -226,7 +218,7 @@ func (fs *OPFS) ReadDir(path string) (infos []os.FileInfo, err error) {
// the JS AsyncIterator has a .next() -> {done, value}
for {
// get one entry
result, err := await(itValue.Call("next")) // {done, value}
result, err := Await(itValue.Call("next")) // {done, value}
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -310,10 +302,10 @@ func (fs *OPFS) Stat(path string) (os.FileInfo, error) {

// try as file first
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/getFileHandle
handle, err := await(parentDirHandle.Call("getFileHandle", name))
handle, err := Await(parentDirHandle.Call("getFileHandle", name))
if err == nil {
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/getFile
file, err := await(handle.Call("getFile")) // returns Promise<File>
file, err := Await(handle.Call("getFile")) // returns Promise<File>
if err != nil {
return nil, err
}
Expand All @@ -327,7 +319,7 @@ func (fs *OPFS) Stat(path string) (os.FileInfo, error) {
}

// if file failed, try as directory
_, err = await(parentDirHandle.Call("getDirectoryHandle", name))
_, err = Await(parentDirHandle.Call("getDirectoryHandle", name))
if err == nil {
return &OPFSFileInfo{
name: name,
Expand Down Expand Up @@ -375,13 +367,13 @@ func (fs *OPFS) applyFlags(f *OPFSFile, flag int) error {
func (fs *OPFS) getDirectoryHandle(path string, create bool) (js.Value, error) {
parts := strings.Split(path, "/")

dir := fs.root
dir := fs.RootHandle
for _, part := range parts {
if part == "" || part == "." {
continue
}

d, err := await(dir.Call("getDirectoryHandle", part, map[string]any{"create": create}))
d, err := Await(dir.Call("getDirectoryHandle", part, map[string]any{"create": create}))
if err != nil {
return js.Undefined(), err
}
Expand All @@ -406,7 +398,7 @@ func (fs *OPFS) split(fullPath string) (string, string) {
// });
//
// But instead of "something", we pass the value/error to Go.
func await(p js.Value) (js.Value, error) {
func Await(p js.Value) (js.Value, error) {
// create channel for each callback
valCh := make(chan js.Value, 1)
errCh := make(chan error, 1)
Expand Down
2 changes: 1 addition & 1 deletion pkg/filesystem/fs_inode_wasm.go → pkg/opfs/inode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//go:build js && wasm

package filesystem
package opfs

import (
"path/filepath"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//go:build js && wasm

package filesystem
package opfs

import "testing"

Expand Down
Loading