Skip to content
Snippets Groups Projects
Commit c9bd2f91 authored by Tamer Tas's avatar Tamer Tas
Browse files

Create metadata for templates

parent de03833d
No related branches found
No related tags found
No related merge requests found
......@@ -59,7 +59,7 @@ func downloadZip(URL, targetDir string) error {
defer rc.Close()
}
// split first token of f.Name since it's zip file name
// splits the first token of f.Name since it's zip file name
path := filepath.Join(dest, strings.SplitAfterN(f.Name, "/", 2)[1])
if f.FileInfo().IsDir() {
......@@ -89,6 +89,7 @@ func downloadZip(URL, targetDir string) error {
}
}
// TODO Wrap this function in a validation wrapper from top to bottom
if _, err := util.ValidateTemplate(targetDir); err != nil {
return err
}
......@@ -134,7 +135,6 @@ var Download = &cli.Command{
zipURL := host.ZipURL(templateURL)
// TODO validate template as well
if err := downloadZip(zipURL, targetDir); err != nil {
// Delete if download transaction fails
defer os.RemoveAll(targetDir)
......@@ -142,6 +142,10 @@ var Download = &cli.Command{
exit.Error(fmt.Errorf("download: %s", err))
}
if err := serializeMetadata(templateName, templateURL, targetDir); err != nil {
exit.Error(fmt.Errorf("download: %s", err))
}
exit.OK("Successfully downloaded the template %v", templateName)
},
}
package cmd
import (
"encoding/json"
"os"
"path/filepath"
"github.com/tmrts/tmplt/pkg/template"
"github.com/tmrts/tmplt/pkg/tmplt"
)
func serializeMetadata(tag string, repo string, targetDir string) error {
fname := filepath.Join(targetDir, tmplt.TemplateMetadataName)
f, err := os.Create(fname)
if err != nil {
return err
} else {
defer f.Close()
}
enc := json.NewEncoder(f)
t := template.Metadata{tag, repo, template.NewTime()}
if err := enc.Encode(&t); err != nil {
return err
}
return nil
}
......@@ -15,6 +15,7 @@ import (
)
var Save = &cli.Command{
// TODO rename template-name to template-tag
Use: "save <template-path> <template-name>",
Short: "Save a project template to local template registry",
Run: func(c *cli.Command, args []string) {
......@@ -53,6 +54,10 @@ var Save = &cli.Command{
exit.Error(err)
}
if err := serializeMetadata(templateName, "local:"+tmplDir, targetDir); err != nil {
exit.Error(fmt.Errorf("save: %s", err))
}
exit.OK("Successfully saved the template %v", templateName)
},
}
package template
import (
"fmt"
"time"
"github.com/docker/go-units"
)
type Metadata struct {
Tag string
Repository string
Created JSONTime
}
func (m Metadata) String() []string {
tDelta := time.Now().Sub(time.Time(m.Created))
return []string{m.Tag, m.Repository, units.HumanDuration(tDelta) + " ago"}
}
type JSONTime time.Time
const (
timeFormat = "Mon Jan 2 15:04 -0700 MST 2006"
)
func NewTime() JSONTime {
return JSONTime(time.Now())
}
func (t *JSONTime) MarshalJSON() ([]byte, error) {
stamp := fmt.Sprintf(`"%s"`, time.Time(*t).Format(timeFormat))
return []byte(stamp), nil
}
func (t *JSONTime) UnmarshalJSON(b []byte) error {
time, err := time.Parse(timeFormat, string(b)[1:len(b)-1])
if err != nil {
return err
}
*t = JSONTime(time)
return nil
}
func (t JSONTime) String() string {
return fmt.Sprintf("%s", time.Time(t).Format(timeFormat))
}
package template_test
import (
"encoding/json"
"testing"
"github.com/tmrts/tmplt/pkg/template"
)
func TestMarshalsTime(t *testing.T) {
jsonT := template.NewTime()
b, err := jsonT.MarshalJSON()
if err != nil {
t.Error(err)
}
var unmarshaledT template.JSONTime
if err := json.Unmarshal(b, &unmarshaledT); err != nil {
t.Error(err)
}
expected, got := jsonT.String(), unmarshaledT.String()
if expected != got {
t.Errorf("marshaled and unmarshaled time should've been equal expected %q, got %q", expected, got)
}
}
......@@ -9,12 +9,18 @@ import (
"github.com/tmrts/tmplt/pkg/prompt"
"github.com/tmrts/tmplt/pkg/tmplt"
"github.com/tmrts/tmplt/pkg/util/osutil"
"github.com/tmrts/tmplt/pkg/util/stringutil"
)
type Interface interface {
Execute(string) error
UseDefaultValues()
Info() Metadata
}
func (t dirTemplate) Info() Metadata {
return t.Metadata
}
func Get(path string) (Interface, error) {
......@@ -49,18 +55,44 @@ func Get(path string) (Interface, error) {
return metadata, nil
}(filepath.Join(absPath, tmplt.ContextFileName))
metadataExists, err := osutil.FileExists(filepath.Join(absPath, tmplt.TemplateMetadataName))
if err != nil {
return nil, err
}
md, err := func() (Metadata, error) {
if !metadataExists {
return Metadata{}, nil
}
b, err := ioutil.ReadFile(filepath.Join(absPath, tmplt.TemplateMetadataName))
if err != nil {
return Metadata{}, err
}
var m Metadata
if err := json.Unmarshal(b, &m); err != nil {
return Metadata{}, err
}
return m, nil
}()
return &dirTemplate{
Context: ctxt,
FuncMap: FuncMap,
Path: filepath.Join(absPath, tmplt.TemplateDirName),
Context: ctxt,
FuncMap: FuncMap,
Path: filepath.Join(absPath, tmplt.TemplateDirName),
Metadata: md,
}, err
}
type dirTemplate struct {
Path string
Context map[string]interface{}
FuncMap template.FuncMap
Path string
Context map[string]interface{}
FuncMap template.FuncMap
Metadata Metadata
alignment string
ShouldUseDefaults bool
}
......@@ -73,6 +105,7 @@ func (t *dirTemplate) BindPrompts() {
for s, v := range t.Context {
t.FuncMap[s] = func() interface{} {
switch v := v.(type) {
// First is the default value if it's a slice
case []interface{}:
return v[0]
}
......@@ -93,6 +126,7 @@ func (t *dirTemplate) Execute(dirPrefix string) error {
// TODO create io.ReadWriter from string
// TODO refactor name manipulation
// TODO trim leading or trailing whitespaces
return filepath.Walk(t.Path, func(filename string, info os.FileInfo, err error) error {
if err != nil {
return err
......
......@@ -9,6 +9,7 @@ import (
"github.com/tmrts/tmplt/pkg/util/exit"
"github.com/tmrts/tmplt/pkg/util/osutil"
"github.com/tmrts/tmplt/pkg/util/tlog"
)
const (
......@@ -19,8 +20,9 @@ const (
ConfigFileName = "config.json"
TemplateDir = "templates"
ContextFileName = "project.json"
TemplateDirName = "template"
ContextFileName = "project.json"
TemplateDirName = "template"
TemplateMetadataName = "__metadata.json"
GithubOwner = "tmrts"
GithubRepo = "tmplt"
......@@ -45,6 +47,17 @@ func init() {
Configuration.FilePath = filepath.Join(homeDir, ConfigDirPath, ConfigFileName)
Configuration.TemplateDirPath = filepath.Join(homeDir, ConfigDirPath, TemplateDir)
IsTemplateDirInitialized, err := osutil.DirExists(Configuration.TemplateDirPath)
if err != nil {
exit.Error(err)
}
// TODO perform this in related commands only with ValidateInitialization
if !IsTemplateDirInitialized {
tlog.Warn("Template registry is not initialized. Please run `init` command to create it.")
return
}
// Read .config/tmplt/config.json if exists
// TODO use defaults if config.json doesn't exist
hasConfig, err := osutil.FileExists(Configuration.FilePath)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment