Skip to content

Commit

Permalink
refactor: cleanup code, add tests for fileops (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
zacowan authored Sep 7, 2024
1 parent 43c4d82 commit 0b30f28
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 41 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: ⚙️ CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Verify dependencies
run: go mod verify

- name: Run go vet
run: go vet ./...

- name: Run tests
run: go test -v -cover ./...
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: goreleaser
name: 🚀 Release

on:
push:
Expand All @@ -15,14 +15,14 @@ jobs:
goreleaser:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch --force --tags
- uses: actions/setup-go@v4
- uses: actions/setup-go@v5
with:
go-version: stable
- uses: goreleaser/goreleaser-action@v5
- uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
Expand Down
19 changes: 3 additions & 16 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strings"

"github.com/spf13/cobra"
"github.com/zacowan/totle/pkg/fileops"
)

// addCmd represents the add command
Expand All @@ -44,7 +45,7 @@ the contents of the note you want to add are appended to that file.`,

createYearMonthDir(notesMeta)

if !PathExists(notesMeta.TodayNotePath) {
if !fileops.PathExists(notesMeta.TodayNotePath) {
titleWithProvidedNoteAsMarkdown := "# " + notesMeta.TodayFormatted.Full + "\n\n- " + providedNote
createNoteFile(notesMeta.TodayNotePath, titleWithProvidedNoteAsMarkdown)
os.Exit(0)
Expand All @@ -59,7 +60,7 @@ the contents of the note you want to add are appended to that file.`,
if lastLineOfNoteFile != "" {
providedNoteAsMarkdown = "\n" + providedNoteAsMarkdown
}
appendToFile(notesMeta.TodayNotePath, providedNoteAsMarkdown)
fileops.AppendToFile(notesMeta.TodayNotePath, providedNoteAsMarkdown)
},
}

Expand All @@ -77,20 +78,6 @@ func init() {
// addCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func appendToFile(path string, contents string) error {
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()

if _, err := file.Write([]byte(contents)); err != nil {
return err
}

return nil
}

func getLastLineOfFile(path string) (lastLine string, err error) {
contents, err := os.ReadFile(path)
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/zacowan/totle/pkg/fileops"
)

// createCmd represents the create command
Expand All @@ -37,7 +37,7 @@ var createCmd = &cobra.Command{

createYearMonthDir(notesMeta)

if !PathExists(notesMeta.TodayNotePath) {
if !fileops.PathExists(notesMeta.TodayNotePath) {
todayAsMarkdownTitle := "# " + notesMeta.TodayFormatted.Full
createNoteFile(notesMeta.TodayNotePath, todayAsMarkdownTitle)
}
Expand All @@ -61,7 +61,7 @@ func init() {
}

func createYearMonthDir(notesMeta NotesMeta) {
created, err := CreateDirectoryIfNotFound(notesMeta.YearMonthDir)
created, err := fileops.CreateDirectoryIfNotFound(notesMeta.YearMonthDir)
if err != nil {
fmt.Println("Failed to create year/month directory", notesMeta.YearMonthDir)
cobra.CheckErr(err)
Expand All @@ -72,7 +72,7 @@ func createYearMonthDir(notesMeta NotesMeta) {
}

func createNoteFile(path string, contents string) {
err := os.WriteFile(path, []byte(contents), os.ModePerm)
err := fileops.CreateFile(path, contents)
if err != nil {
fmt.Println("Failed to create note file at", path)
cobra.CheckErr(err)
Expand Down
3 changes: 2 additions & 1 deletion cmd/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zacowan/totle/pkg/fileops"
)

// openCmd represents the open command
Expand Down Expand Up @@ -59,7 +60,7 @@ func openNoteFile(notesMeta NotesMeta) {
}

func openWithCmd(cmd string, path string, arg ...string) {
if !PathExists(path) {
if !fileops.PathExists(path) {
fmt.Println("Failed to open - no note file exists at", path)
return
}
Expand Down
16 changes: 0 additions & 16 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,6 @@ func GetNotesMeta() NotesMeta {
return notesMeta
}

func CreateDirectoryIfNotFound(path string) (created bool, err error) {
if !PathExists(path) {
err = os.MkdirAll(path, os.ModePerm)
return err != nil, err
}
return false, nil
}

func PathExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
return !os.IsNotExist(err)
}

// See https://gosamples.dev/date-format-yyyy-mm-dd/#:~:text=To%20format%20date%20in%20Go,%2F01%2F2006%22%20layout.
func getTodayFormatted() TodayFormatted {
now := time.Now().Local()
Expand Down
50 changes: 50 additions & 0 deletions pkg/fileops/fileops.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package fileops

import (
"os"
)

// CreateDir creates a directory and all necessary parent directories.
// It returns an error if the operation fails.
func CreateDir(path string) error {
return os.MkdirAll(path, os.ModePerm)
}

// CreateFile creates a new file with the given content.
// It returns an error if the file cannot be created or written to.
func CreateFile(path, content string) error {
return os.WriteFile(path, []byte(content), 0644)
}

// PathExists checks if a file or directory exists.
// It returns true if the path exists, false otherwise.
func PathExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}

// AppendToFile appends content to an existing file or creates a new one if it doesn't exist.
// It returns an error if the file cannot be opened, created, or written to.
func AppendToFile(path, content string) error {
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(content)
return err
}

// CreateDirectoryIfNotFound creates a directory if it doesn't exist.
// It returns true if the directory was created, false if it already existed.
// If an error occurs during creation, it returns false and the error.
func CreateDirectoryIfNotFound(path string) (bool, error) {
if !PathExists(path) {
err := CreateDir(path)
if err != nil {
return false, err
}
return true, nil
}
return false, nil
}
152 changes: 152 additions & 0 deletions pkg/fileops/fileops_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package fileops

import (
"os"
"path/filepath"
"testing"
)

func TestCreateDir(t *testing.T) {
testDir := filepath.Join(os.TempDir(), "test_create_dir")
defer os.RemoveAll(testDir)

err := CreateDir(testDir)
if err != nil {
t.Fatalf("CreateDir failed: %v", err)
}

if !PathExists(testDir) {
t.Errorf("Directory was not created")
}
}

func TestCreateFile(t *testing.T) {
testFile := filepath.Join(os.TempDir(), "test_create_file.txt")
defer os.Remove(testFile)

content := "Test content"
err := CreateFile(testFile, content)
if err != nil {
t.Fatalf("CreateFile failed: %v", err)
}

if !PathExists(testFile) {
t.Errorf("File was not created")
}

data, err := os.ReadFile(testFile)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}

if string(data) != content {
t.Errorf("File content does not match. Expected: %s, Got: %s", content, string(data))
}
}

func TestCreateFileInNonExistentDir(t *testing.T) {
nonExistentDir := filepath.Join(os.TempDir(), "non_existent_dir")
nonExistentFile := filepath.Join(nonExistentDir, "test.txt")
defer os.RemoveAll(nonExistentDir)

err := CreateFile(nonExistentFile, "content")
if err == nil {
t.Errorf("CreateFile should fail when creating file in non-existent directory")
}
}

func TestPathExists(t *testing.T) {
existingFile := filepath.Join(os.TempDir(), "existing_file.txt")
err := os.WriteFile(existingFile, []byte("test"), 0644)
if err != nil {
t.Fatalf("Failed to create test file: %v", err)
}
defer os.Remove(existingFile)

if !PathExists(existingFile) {
t.Errorf("PathExists returned false for an existing file")
}
}

func TestPathDoesNotExist(t *testing.T) {
nonExistingFile := filepath.Join(os.TempDir(), "non_existing_file.txt")

if PathExists(nonExistingFile) {
t.Errorf("PathExists returned true for a non-existing file")
}
}

func TestAppendToFile(t *testing.T) {
testFile := filepath.Join(os.TempDir(), "test_append_file.txt")
defer os.Remove(testFile)

initialContent := "Initial content\n"
appendedContent := "Appended content"

err := CreateFile(testFile, initialContent)
if err != nil {
t.Fatalf("Failed to create initial file: %v", err)
}

err = AppendToFile(testFile, appendedContent)
if err != nil {
t.Fatalf("AppendToFile failed: %v", err)
}

data, err := os.ReadFile(testFile)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}

expectedContent := initialContent + appendedContent
if string(data) != expectedContent {
t.Errorf("File content does not match. Expected: %s, Got: %s", expectedContent, string(data))
}
}

func TestAppendToReadOnlyFile(t *testing.T) {
readOnlyFile := filepath.Join(os.TempDir(), "readonly_file.txt")
err := os.WriteFile(readOnlyFile, []byte("Read-only content"), 0444)
if err != nil {
t.Fatalf("Failed to create read-only file: %v", err)
}
defer os.Remove(readOnlyFile)

err = AppendToFile(readOnlyFile, "Appended content")
if err == nil {
t.Errorf("AppendToFile should fail when appending to a read-only file")
}
}

func TestCreateDirectoryIfNotFound(t *testing.T) {
testDir := filepath.Join(os.TempDir(), "test_create_dir_if_not_found")
defer os.RemoveAll(testDir)

created, err := CreateDirectoryIfNotFound(testDir)
if err != nil {
t.Fatalf("CreateDirectoryIfNotFound failed: %v", err)
}
if !created {
t.Errorf("CreateDirectoryIfNotFound returned false for a new directory")
}
if !PathExists(testDir) {
t.Errorf("Directory was not created")
}
}

func TestCreateExistingDirectory(t *testing.T) {
testDir := filepath.Join(os.TempDir(), "test_create_existing_dir")
err := os.Mkdir(testDir, 0755)
if err != nil {
t.Fatalf("Failed to create test directory: %v", err)
}
defer os.RemoveAll(testDir)

created, err := CreateDirectoryIfNotFound(testDir)
if err != nil {
t.Fatalf("CreateDirectoryIfNotFound failed for existing directory: %v", err)
}
if created {
t.Errorf("CreateDirectoryIfNotFound returned true for an existing directory")
}
}

0 comments on commit 0b30f28

Please sign in to comment.