template / commit
Got piping working, added example to the readme, and added piping test.
.vscode/launch.json | 12 +++++- README.md | 43 ++++++++++++------- default_config.go | 119 ++++++++++++++++++++++++++++++---------------------- file.go | 27 +++++++++++- file_test.go | 35 ++++++++++++++-- main.go | 48 ++++++++++----------- monkey-patch.go | 15 +++++++ profile.go | 31 ++++++-------- profile_test.go | 14 ++++--- 9 files changed, 223 insertions(+), 121 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 13d3f1a..882bd7c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,7 +4,6 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { "name": "Launch tests", "type": "go", @@ -72,6 +71,17 @@ "daily" ] }, + { + "name": "Run: template log", + "type": "go", + "request": "launch", + "mode": "auto", + "program": ".", + "args": [ + "log" + ], + "console": "integratedTerminal" + }, { "name": "Run: template work test-project w/ in-memory defaults", "type": "go", diff --git a/README.md b/README.md index 9cb0997..7f91302 100644 --- a/README.md +++ b/README.md @@ -25,29 +25,29 @@ This is one of the profiles that comes with the tool. isdefault: false isdisabled: false type: file - path: ~/DailyNotes - namepatterns: - - '{{$version := getVersion}}{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}{{if (gt $version 1)}}v{{$version}}{{end}}.md' runpostscriptonfailure: true postscripts: - code . {{ if .FullPath }}"{{.FullPath}}"{{else}}(ls -t | head -n1){{ end }} - file: - template: |- - # {{.FileNameWithoutExtension}} + namepatterns: + - '{{$version := getVersion}}{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}{{if (gt $version 1)}}v{{$version}}{{end}}.md' + targetdirectory: ~/DailyNotes + filetemplate: |- + # {{.FileNameWithoutExtension}} - Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. + Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. - ## Todo + ## Todo - 1. Check email - 2. Check chat - 3. Check calendar - 4. Check yesterday's notes - 5. Have fun! - 6. ADD MORE ITEMS HERE + 1. Check email + 2. Check chat + 3. Check calendar + 4. Check yesterday's notes + 5. Have fun! + 6. ADD MORE ITEMS HERE ``` Using the above configuration: + ```sh > $ template daily "Cool Thought" Profile: daily @@ -64,6 +64,21 @@ This will cause VSCode to open the `~\DailyNotes` folder as a workspace, and the The above example also uses the [`snakecase`](https://github.com/Masterminds/sprig/blob/master/docs/strings.md#user-content-snakecase) template function. This is one of the [sprig template functions](https://github.com/Masterminds/sprig/blob/master/docs/index.md) that are exposed by template. +File-based profiles (`type: file`) can accept piped input, and this input will be piped to the created file. +In this instance, the profile's file template field is ignored. +Here's an example of piping the results of `ps` to a file with an auto-generated name: + +```sh +> $ echo "$(ps)" | go run . log "ps-info" +Profile: log +Project name: ps-info +Loaded config from /Users/pavel/.template.yaml +Loaded user config from /Users/pavel/.template.user.yaml, combining with global config +Creating file: 2022-12-10-00-05-21-ps-info.log +Executing post script: sh -c code . 2022-12-10-00-05-21-ps-info.log +Post script had no output +``` + Note that user profiles are combined with the default ones. This is so you can run `template reset` to reset `~/.template.yaml`, but keep your local profiles/changes as-is. diff --git a/default_config.go b/default_config.go index d800add..fa4e813 100644 --- a/default_config.go +++ b/default_config.go @@ -4,10 +4,10 @@ func defaultConfig() Config { config := Config{ Profiles: []Profile{ { - Name: "daily", - Description: "Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md", - TargetDirectory: "~/DailyNotes", - Type: FileType, + Name: "daily", + Description: "Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md", + TargetDirectory: "~/DailyNotes", + Type: FileType, NamePatterns: []ParameterizedText{ "{{$version := getVersion}}" + "{{.Year}}-{{.Month}}-{{.Day}}" + @@ -33,11 +33,11 @@ Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. RunPostscriptOnFailure: true, }, { - Name: "note", - Description: "Creates a MD file in ~/Notes in the format YYYY-MM-DD[-ProjectName][-vVersion].md", - OS: "All", - TargetDirectory: "~/Notes", - Type: FileType, + Name: "note", + Description: "Creates a MD file in ~/Notes in the format YYYY-MM-DD[-ProjectName][-vVersion].md", + OS: "All", + TargetDirectory: "~/Notes", + Type: FileType, NamePatterns: []ParameterizedText{ "{{$version := getVersion}}" + "{{.Year}}-{{.Month}}-{{.Day}}" + @@ -50,12 +50,12 @@ Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. }, }, { - Name: "note-here", - Description: "Creates a MD file in the current folder in the format YYYY-MM-DD[-HH[-MM[-SS]]][-ProjectName][-vVersion].md", - OS: "All", - Type: FileType, - IsDefault: true, - TargetDirectory: ".", // current folder + Name: "note-here", + Description: "Creates a MD file in the current folder in the format YYYY-MM-DD[-HH[-MM[-SS]]][-ProjectName][-vVersion].md", + OS: "All", + Type: FileType, + IsDefault: true, + TargetDirectory: ".", // current folder NamePatterns: []ParameterizedText{ "{{$version := getVersion}}" + "{{.Year}}-{{.Month}}-{{.Day}}" + @@ -68,7 +68,12 @@ Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. "{{if (gt $version 1)}}n{{$version}}{{end}}" + ".md", "{{$version := getVersion}}" + - "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Second}}" + + "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}" + + "{{if .ProjectName}}-{{.ProjectName}}{{end}}" + + "{{if (gt $version 1)}}n{{$version}}{{end}}" + + ".md", + "{{$version := getVersion}}" + + "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}" + "{{if .ProjectName}}-{{.ProjectName}}{{end}}" + "{{if (gt $version 1)}}n{{$version}}{{end}}" + ".md", @@ -78,10 +83,10 @@ Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. }, }, { - Name: "blog", - Description: "Creates a MD file in the ~/Blog folder in the format YYYY-MM-DD[-ProjectName][-vVersion].md", - OS: "All", - TargetDirectory: "~/Blog", + Name: "blog", + Description: "Creates a MD file in the ~/Blog folder in the format YYYY-MM-DD[-ProjectName][-vVersion].md", + OS: "All", + TargetDirectory: "~/Blog", FileTemplate: `# {{.ProjectName}} Created by template, on {{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}. @@ -107,11 +112,11 @@ cspell:words nanite }, }, { - Name: "work-win", - Description: "Creates a folder in the c:/work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", - OS: "Windows", - TargetDirectory: "C:/work", - Type: FolderType, + Name: "work-win", + Description: "Creates a folder in the c:/work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", + OS: "Windows", + TargetDirectory: "C:/work", + Type: FolderType, NamePatterns: []ParameterizedText{ "{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", @@ -123,10 +128,10 @@ cspell:words nanite }, }, { - Name: "therapy", - Description: "Creates a MD file in the ~/Therapy folder in the format YYYY-MM-DD[-vVersion].md", - OS: "All", - TargetDirectory: "~/Therapy", + Name: "therapy", + Description: "Creates a MD file in the ~/Therapy folder in the format YYYY-MM-DD[-vVersion].md", + OS: "All", + TargetDirectory: "~/Therapy", FileTemplate: `# {{if .ProjectName}}{{.ProjectName}}{{else}}Therapy notes{{end}} {{if .ProjectName}}Therapy notes on {{.ProjectName}}{{else}}Therapy notes{{end}} @@ -151,10 +156,10 @@ Sincerely, me }, }, { - Name: "work", - Description: "Creates a folder in the ~/Work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", - TargetDirectory: "~/Work", - Type: FolderType, + Name: "work", + Description: "Creates a folder in the ~/Work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", + TargetDirectory: "~/Work", + Type: FolderType, NamePatterns: []ParameterizedText{ "{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", @@ -199,11 +204,11 @@ echo "Let's test {{.ProjectName}}!"`, }, }, { - Name: "folder", - Description: "Creates a folder in the current folder in the format YYYY-MM-DD[-ProjectName][-vVersion]", - Type: FolderType, - TargetDirectory: ".", // current folder - PostScripts: []ParameterizedText{}, + Name: "folder", + Description: "Creates a folder in the current folder in the format YYYY-MM-DD[-ProjectName][-vVersion]", + Type: FolderType, + TargetDirectory: ".", // current folder + PostScripts: []ParameterizedText{}, NamePatterns: []ParameterizedText{ "{{$version := getVersion}}" + "{{.Year}}-{{.Month}}-{{.Day}}" + @@ -212,10 +217,10 @@ echo "Let's test {{.ProjectName}}!"`, }, }, { - Name: "create-react-app", - Type: FolderType, - Description: "Creates a folder in the current folder in the format create-react-app[-ProjectName][-vVersion], runs `npx create-react-app` to initialize the folder, and opens the folder in VSCode", - TargetDirectory: ".", // current folder + Name: "create-react-app", + Type: FolderType, + Description: "Creates a folder in the current folder in the format create-react-app[-ProjectName][-vVersion], runs `npx create-react-app` to initialize the folder, and opens the folder in VSCode", + TargetDirectory: ".", // current folder NamePatterns: []ParameterizedText{ "{{$version := getVersion}}" + "create-react-app" + @@ -228,10 +233,10 @@ echo "Let's test {{.ProjectName}}!"`, }, }, { - Name: "git", - Description: "Creates a folder in the ~/code folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", - TargetDirectory: "~/code", - Type: FolderType, + Name: "git", + Description: "Creates a folder in the ~/code folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", + TargetDirectory: "~/code", + Type: FolderType, NamePatterns: []ParameterizedText{ "{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", @@ -244,11 +249,11 @@ echo "Let's test {{.ProjectName}}!"`, }, }, { - Name: "git-clone", - Description: "DISABLED - Clones a repository into a new folder under ~/code in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", - IsDisabled: true, - TargetDirectory: "~/code", - Type: FolderType, + Name: "git-clone", + Description: "DISABLED - Clones a repository into a new folder under ~/code in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]", + IsDisabled: true, + TargetDirectory: "~/code", + Type: FolderType, NamePatterns: []ParameterizedText{ "{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}", @@ -260,6 +265,18 @@ echo "Let's test {{.ProjectName}}!"`, "code .", }, }, + { + Name: "log", + Description: "Creates a log file in the current folder", + Type: FileType, + NamePatterns: []ParameterizedText{ + "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.log", + }, + TargetDirectory: ".", + PostScripts: []ParameterizedText{ + "code . {{.FullPath}}", + }, + }, }, } diff --git a/file.go b/file.go index 2be8d22..2b451fe 100644 --- a/file.go +++ b/file.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "fmt" "os" "strings" @@ -12,9 +13,31 @@ import ( func createFile( prePatternData PrePatternData, fileTemplate ParameterizedText, - fullPath string) error { + fullPath string, + pipeInputScanner *bufio.Scanner) error { + useTemplate := fileTemplate != "" - if useTemplate { + useInputPipe := pipeInputScanner != nil + + if useInputPipe { + log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from input pipe content", fullPath) + + file, err := monkey.OSCreate(fullPath) + if err != nil { + return fmt.Errorf("error creating file: %v", err) + } + defer file.Close() + + writer := bufio.NewWriter(file) + for pipeInputScanner.Scan() { + line := pipeInputScanner.Text() + _, err := writer.WriteString(line + "\n") + if err != nil { + return fmt.Errorf("error writing file: %v", err) + } + } + writer.Flush() + } else if useTemplate { postPatternData := createPostPatternData(fullPath, prePatternData) log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from template string\n", fullPath) diff --git a/file_test.go b/file_test.go index a53896c..7a75ed5 100644 --- a/file_test.go +++ b/file_test.go @@ -1,7 +1,9 @@ package main import ( + "bufio" "os" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -12,9 +14,18 @@ func TestCreateFile(t *testing.T) { path := "~/test/out/test.txt" prePatternData := testPrePatternData() expectedText := "test-project-2022-04-20-16-20-69-value1" + var createdFileName = "" // monkey patch applyTestMonkeyPatch(t, monkeyPatch{ + OSCreate: func(filename string) (*os.File, error) { + assert.Equal(t, path, filename) + file, err := os.CreateTemp("./test", "test") + assert.Nil(t, err, "error creating temp file") + assert.True(t, createdFileName == "", "createFileName should be empty") + createdFileName = file.Name() + return file, nil + }, OSWriteFile: func(filename string, data []byte, perm os.FileMode) error { assert.Equal(t, path, filename) assert.Equal(t, perm, os.ModePerm) @@ -24,15 +35,31 @@ func TestCreateFile(t *testing.T) { }) // test error path - err := createFile(prePatternData, "{{.ProjectName", path) + err := createFile(prePatternData, "{{.ProjectName", path, nil) assert.NotNil(t, err) - // test happy path - err = createFile(prePatternData, "{{.ProjectName}}-{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.Extras.key1}}",path) + // test happy path with file template + err = createFile(prePatternData, "{{.ProjectName}}-{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.Extras.key1}}", path, nil) + assert.Nil(t, err) + + // test happy path with pipe input + inputText := `line1 +line2 +line3 +` + expectedText = inputText + reader := strings.NewReader(inputText) + pipeInputScanner := bufio.NewScanner(reader) + err = createFile(prePatternData, "{{.ProjectName}}-{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.Extras.key1}}", path, pipeInputScanner) assert.Nil(t, err) + assert.NotNil(t, createdFileName) + bytes, err := os.ReadFile(createdFileName) + assert.Nil(t, err, "error reading file "+createdFileName) + outputText := string(bytes) + assert.Equal(t, inputText, outputText) // test empty template expectedText = "" - err = createFile(prePatternData, "", path) + err = createFile(prePatternData, "", path, nil) assert.Nil(t, err) } diff --git a/main.go b/main.go index ab3e976..2a8abd0 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "fmt" "os" "os/user" @@ -30,11 +31,10 @@ type EnvVarValues struct { type Settings struct { ArgumentValues EnvVarValues - extras map[string]string - fullConfigPath string - config Config - usr *user.User - outputToTerminal bool + extras map[string]string + fullConfigPath string + config Config + usr *user.User } func main() { @@ -189,16 +189,9 @@ func createSettings( return Settings{}, fmt.Errorf("error getting env var values: %w", err) } - stat, err := os.Stdout.Stat() - if err != nil { - return Settings{}, fmt.Errorf("error getting stdout stat: %w", err) - } - outputToTerminal := (stat.Mode() & os.ModeCharDevice) == 0 - settings := Settings{ - ArgumentValues: argumentValues, - EnvVarValues: envVarValues, - outputToTerminal: outputToTerminal, + ArgumentValues: argumentValues, + EnvVarValues: envVarValues, } // read args @@ -231,18 +224,14 @@ func createSettings( if settings.profile == "" && args.Len() > 0 { settings.profile = args.Get(0) } - if !outputToTerminal { - fmt.Println("Profile:", settings.profile) - } + fmt.Println("Profile:", settings.profile) // get project name from args // if not set explicitly, use second arg, if present if settings.projectName == "" && args.Len() > 1 { settings.projectName = args.Get(1) } - if !outputToTerminal { - fmt.Println("Project name:", settings.projectName) - } + fmt.Println("Project name:", settings.projectName) // extras strings _, err = os.Stat(settings.extrasFilePath) @@ -272,9 +261,9 @@ func createSettings( config, err = loadConfig(fullConfigPath) if err != nil { return settings, fmt.Errorf("error loading config from %v: %w", fullConfigPath, err) - } else if !outputToTerminal { - fmt.Printf("Loaded config from %v\n", fullConfigPath) } + fmt.Printf("Loaded config from %v\n", fullConfigPath) + // load user config, if present fullUserConfigPath := getFullPath(settings.userConfigPath, *usr) _, err = os.Stat(fullUserConfigPath) @@ -283,9 +272,7 @@ func createSettings( if err != nil { return settings, fmt.Errorf("error loading user config from %v: %w", fullUserConfigPath, err) } else { - if !outputToTerminal { - fmt.Printf("Loaded user config from %v, combining with global config\n", fullUserConfigPath) - } + fmt.Printf("Loaded user config from %v, combining with global config\n", fullUserConfigPath) config, err = mergeConfigs(config, userConfig) if err != nil { return settings, fmt.Errorf("error merging configs: %w", err) @@ -339,8 +326,17 @@ func mainLogic(settings Settings) error { return fmt.Errorf("error finding profile: %v", err) } + var pipeInputScanner *bufio.Scanner = nil + stat, err := os.Stdin.Stat() + if err != nil { + return fmt.Errorf("error getting stdin stat: %w", err) + } + if stat.Size() > 0 { + pipeInputScanner = bufio.NewScanner(os.Stdin) + } + // process profile - errors := processProfile(profile, settings.projectName, settings.extras, *settings.usr) + errors := processProfile(profile, settings.projectName, settings.extras, *settings.usr, pipeInputScanner) if len(errors) > 0 { return fmt.Errorf("error processing profile: %v", errors) } diff --git a/monkey-patch.go b/monkey-patch.go index 26a6ec9..d0b0796 100644 --- a/monkey-patch.go +++ b/monkey-patch.go @@ -10,6 +10,7 @@ import ( type monkeyPatch struct { ExecCommand func(name string, arg ...string) *exec.Cmd + OSCreate func(name string) (*os.File, error) OSWriteFile func(filename string, data []byte, perm os.FileMode) error OSGetwd func() (string, error) OSChdir func(dir string) error @@ -22,6 +23,9 @@ type monkeyPatchCalls struct { name string arg []string } + OSCreateCalls []struct { + name string + } OSWriteFileCalls []struct { filename string data []byte @@ -45,6 +49,9 @@ func applyTestMonkeyPatch(t *testing.T, monkeyImpl monkeyPatch) *monkeyPatchCall name string arg []string }{}, + OSCreateCalls: []struct { + name string + }{}, OSWriteFileCalls: []struct { filename string data []byte @@ -67,6 +74,13 @@ func applyTestMonkeyPatch(t *testing.T, monkeyImpl monkeyPatch) *monkeyPatchCall }{name, arg}) return monkeyImpl.ExecCommand(name, arg...) }, + OSCreate: func(name string) (*os.File, error) { + assert.NotNil(t, monkeyImpl.OSCreate, "OSCreate is not implemented") + results.OSCreateCalls = append(results.OSCreateCalls, struct { + name string + }{name}) + return monkeyImpl.OSCreate(name) + }, OSWriteFile: func(filename string, data []byte, perm os.FileMode) error { assert.NotNil(t, monkeyImpl.OSWriteFile, "OSWriteFile is not implemented") results.OSWriteFileCalls = append(results.OSWriteFileCalls, struct { @@ -106,6 +120,7 @@ func applyTestMonkeyPatch(t *testing.T, monkeyImpl monkeyPatch) *monkeyPatchCall func defaultMonkeyPatch() monkeyPatch { return monkeyPatch{ ExecCommand: exec.Command, + OSCreate: os.Create, OSWriteFile: os.WriteFile, OSGetwd: os.Getwd, OSChdir: os.Chdir, diff --git a/profile.go b/profile.go index ca7d90d..5f727a0 100644 --- a/profile.go +++ b/profile.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "bytes" "fmt" "os" @@ -19,14 +20,12 @@ const ( FileType ProfileType = "file" FolderType ProfileType = "folder" ScriptType ProfileType = "script" - DirectType ProfileType = "direct" ) var allProfileTypes = []ProfileType{ FileType, FolderType, ScriptType, - DirectType, } type OSType string @@ -66,7 +65,7 @@ var forbiddenProfileNames = []string{ "get", } -func processProfile(profile Profile, projectName string, extras map[string]string, usr user.User) []error { +func processProfile(profile Profile, projectName string, extras map[string]string, usr user.User, pipeInputScanner *bufio.Scanner) []error { if profile.IsDisabled { return []error{fmt.Errorf("Profile is disabled, doing nothing")} } @@ -88,7 +87,7 @@ func processProfile(profile Profile, projectName string, extras map[string]strin profileType := profile.Type cwd, err := monkey.OSGetwd() - if err != nil && profileType != DirectType { + if err != nil { return []error{fmt.Errorf("unable to get current working directory: %v", err)} } if profile.TargetDirectory != "" { @@ -107,6 +106,11 @@ func processProfile(profile Profile, projectName string, extras map[string]strin prePatternData := createPrePatternData(now, projectName, extras) if profileType == FileType || profileType == FolderType { + if pipeInputScanner != nil && profileType != FileType { + errors = append(errors, fmt.Errorf("cannot use pipe input with non-file type profile")) + return errors + } + // get all entities in current directory files, err := monkey.OSReadDir(cwd) if err != nil { @@ -138,7 +142,7 @@ func processProfile(profile Profile, projectName string, extras map[string]strin } if err == nil && newName != "" { - fullPath, err = createEntity(now, profile, cwd, newName, projectName, extras, prePatternData) + fullPath, err = createEntity(now, profile, cwd, newName, projectName, extras, prePatternData, pipeInputScanner) if err != nil { if swallowPrePostScriptErrors { fmt.Printf("Error creating entity, but will attempt to run post scripts: %v", err) @@ -217,7 +221,8 @@ func createEntity( newName string, projectName string, extras map[string]string, - prePatternData PrePatternData) (string, error) { + prePatternData PrePatternData, + pipeInputScanner *bufio.Scanner) (string, error) { profileType := profile.Type fullPath := filepath.Join(cwd, newName) @@ -255,7 +260,7 @@ func createEntity( } } fmt.Printf("Creating sub file: %v\n", subFilePath) - err = createFile(filePrePatternData, file.FileTemplate, subFilePath) + err = createFile(filePrePatternData, file.FileTemplate, subFilePath, nil) if err != nil { return "", fmt.Errorf("error creating file %v: %v", subFilePath, err) } @@ -263,7 +268,7 @@ func createEntity( } } else if profileType == FileType { fmt.Printf("Creating file: %v\n", fullPath) - err := createFile(prePatternData, profile.FileTemplate, fullPath) + err := createFile(prePatternData, profile.FileTemplate, fullPath, pipeInputScanner) if err != nil { return "", err } @@ -318,16 +323,6 @@ func validateProfile(profile *Profile) error { } } - // check DirectType profile - if profile.Type == DirectType { - if profile.TargetDirectory != "" { - return fmt.Errorf("targetDirectory is not supported for profile %s, which has Type=%s", profile.Name, profile.Type) - } - if profile.FileTemplate != "" { - return fmt.Errorf("fileTemplate is not supported for profile %s, which has Type=%s", profile.Name, profile.Type) - } - } - // set files to empty array if nil if profile.Files == nil { profile.Files = []FileInFolder{} diff --git a/profile_test.go b/profile_test.go index ee435fc..c34f84d 100644 --- a/profile_test.go +++ b/profile_test.go @@ -171,7 +171,7 @@ func TestCreateEntity(t *testing.T) { newName := "new-name" expectedFullPath := filepath.Clean("~/test/dir/" + newName) - fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData) + fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData, nil) assert.Nil(t, err) assert.Equal(t, expectedFullPath, fullPath) assert.Equal(t, 1, len(monkeyPatchCalls.OSChdirCalls)) @@ -196,7 +196,7 @@ func TestCreateEntity(t *testing.T) { } newName := "new-name.md" expectedFullPath := filepath.Clean("~/test/dir/" + newName) - fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData) + fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData, nil) assert.Nil(t, err) assert.Equal(t, expectedFullPath, fullPath) assert.Equal(t, 1, len(monkeyPatchCalls.OSWriteFileCalls)) @@ -213,7 +213,7 @@ func TestCreateEntity(t *testing.T) { } newName := "new-name.md" expectedFullPath := filepath.Clean("~/test/dir/" + newName) - fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData) + fullPath, err := createEntity(now, profile, cwd, newName, projectName, extras, patternData, nil) assert.Nil(t, err) assert.Equal(t, expectedFullPath, fullPath) } @@ -248,6 +248,10 @@ func TestProcessProfile(t *testing.T) { shell, shellArgs := shellCommandAndArgs("echo") return exec.Command(shell, shellArgs...) }, + OSCreate: func(name string) (file *os.File, err error) { + dir := os.TempDir() + return os.CreateTemp(dir, "test") + }, OSChdir: func(dir string) error { return nil }, OSGetwd: func() (dir string, err error) { return cwd, nil }, OSReadDir: func(dirname string) ([]os.DirEntry, error) { @@ -275,7 +279,7 @@ func TestProcessProfile(t *testing.T) { testSuccess := func(profile Profile) { configureMonkeyPatching() - errors := processProfile(profile, projectName, extras, *usr) + errors := processProfile(profile, projectName, extras, *usr, nil) assert.Equal(t, 0, len(errors)) for _, error := range errors { assert.Nil(t, error) @@ -283,7 +287,7 @@ func TestProcessProfile(t *testing.T) { } testFailure := func(profile Profile, errorCount int, errorStr string) { configureMonkeyPatching() - errors := processProfile(profile, projectName, extras, *usr) + errors := processProfile(profile, projectName, extras, *usr, nil) assert.Equal(t, errorCount, len(errors)) allErrorsText := "" for _, err := range errors {