zk/core/note/index.go

107 lines
2.4 KiB
Go
Raw Normal View History

2021-01-03 16:09:10 +00:00
package note
2021-01-03 13:43:27 +00:00
import (
"crypto/sha256"
"fmt"
"io/ioutil"
"strings"
"time"
2021-01-03 16:09:10 +00:00
"github.com/mickael-menu/zk/core/file"
"github.com/mickael-menu/zk/core/zk"
2021-01-03 13:43:27 +00:00
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/errors"
"gopkg.in/djherbis/times.v1"
)
2021-01-03 16:09:10 +00:00
// Metadata holds information about a particular note.
type Metadata struct {
Path file.Path
2021-01-03 13:43:27 +00:00
Title string
Body string
WordCount int
Created time.Time
Modified time.Time
Checksum string
}
2021-01-03 16:09:10 +00:00
// Indexer persists the notes index.
2021-01-03 13:43:27 +00:00
type Indexer interface {
2021-01-03 16:09:10 +00:00
// Indexed returns the list of indexed note file metadata.
Indexed() (<-chan file.Metadata, error)
// Add indexes a new note from its metadata.
Add(metadata Metadata) error
// Update updates the metadata of an already indexed note.
Update(metadata Metadata) error
// Remove deletes a note from the index.
Remove(path file.Path) error
2021-01-03 13:43:27 +00:00
}
// Index indexes the content of the notes in the given directory.
2021-01-03 16:09:10 +00:00
func Index(dir zk.Dir, indexer Indexer, logger util.Logger) error {
2021-01-03 13:43:27 +00:00
wrap := errors.Wrapper("indexation failed")
source := file.Walk(dir, dir.Config.Extension, logger)
2021-01-03 13:43:27 +00:00
target, err := indexer.Indexed()
if err != nil {
return wrap(err)
}
2021-01-03 16:09:10 +00:00
err = file.Diff(source, target, func(change file.DiffChange) error {
2021-01-03 13:43:27 +00:00
switch change.Kind {
2021-01-03 16:09:10 +00:00
case file.DiffAdded:
metadata, err := metadata(change.Path)
2021-01-03 13:43:27 +00:00
if err == nil {
err = indexer.Add(metadata)
}
logger.Err(err)
2021-01-03 16:09:10 +00:00
case file.DiffModified:
metadata, err := metadata(change.Path)
2021-01-03 13:43:27 +00:00
if err == nil {
err = indexer.Update(metadata)
}
logger.Err(err)
2021-01-03 16:09:10 +00:00
case file.DiffRemoved:
err := indexer.Remove(change.Path)
logger.Err(err)
2021-01-03 13:43:27 +00:00
}
return nil
})
2021-01-03 16:09:10 +00:00
return wrap(err)
2021-01-03 13:43:27 +00:00
}
2021-01-03 16:09:10 +00:00
// metadata retrieves note metadata for the given file.
func metadata(path file.Path) (Metadata, error) {
metadata := Metadata{
2021-01-03 13:43:27 +00:00
Path: path,
}
content, err := ioutil.ReadFile(path.Abs)
if err != nil {
return metadata, err
}
contentStr := string(content)
2021-01-03 21:19:23 +00:00
contentParts := Parse(contentStr)
metadata.Title = contentParts.Title
metadata.Body = contentParts.Body
2021-01-03 13:43:27 +00:00
metadata.WordCount = len(strings.Fields(contentStr))
metadata.Checksum = fmt.Sprintf("%x", sha256.Sum256(content))
times, err := times.Stat(path.Abs)
if err != nil {
return metadata, err
}
metadata.Modified = times.ModTime()
if times.HasBirthTime() {
metadata.Created = times.BirthTime()
} else {
metadata.Created = time.Now()
}
return metadata, nil
}