diff --git a/cmd/build.go b/cmd/build.go index 1e9dabab..74eca462 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "plenti/cmd/build" + "plenti/common" "plenti/readers" "time" @@ -68,15 +69,18 @@ func Build() { buildDir := setBuildDir(siteConfig) tempBuildDir := "" + var err error // Get theme from plenti.json. theme := siteConfig.Theme // If a theme is set, run the nested build. if theme != "" { themeOptions := siteConfig.ThemeConfig[theme] // Recursively copy all nested themes to a temp folder for building. - tempBuildDir = build.ThemesCopy("themes/"+theme, themeOptions) + tempBuildDir, err = build.ThemesCopy("themes/"+theme, themeOptions) + common.CheckErr(err) // Merge the current project files with the theme. - build.ThemesMerge(tempBuildDir, buildDir) + err = build.ThemesMerge(tempBuildDir, buildDir) + common.CheckErr(err) } // Get the full path for the build directory of the site. @@ -84,12 +88,9 @@ func Build() { // Clear out any previous build dir of the same name. if _, buildPathExistsErr := os.Stat(buildPath); buildPathExistsErr == nil { - deleteBuildErr := os.RemoveAll(buildPath) build.Log("Removing old '" + buildPath + "' build directory") - if deleteBuildErr != nil { - log.Fatal(deleteBuildErr) - } + common.CheckErr(os.RemoveAll(buildPath)) } // Create the buildPath directory. @@ -101,44 +102,52 @@ func Build() { build.Log("Creating '" + buildDir + "' build directory") // Add core NPM dependencies if node_module folder doesn't already exist. - build.NpmDefaults(tempBuildDir) + err = build.NpmDefaults(tempBuildDir) + common.CheckErr(err) // Write ejectable core files to filesystem before building. - tempFiles, ejectedPath := build.EjectTemp(tempBuildDir) + tempFiles, ejectedPath, err := build.EjectTemp(tempBuildDir) + common.CheckErr(err) // Directly copy .js that don't need compiling to the build dir. - build.EjectCopy(buildPath, tempBuildDir, ejectedPath) + if err = build.EjectCopy(buildPath, tempBuildDir, ejectedPath); err != nil { + log.Fatal(err) + } // Bundle the JavaScript dependencies needed for the build. //bundledContent := build.Bundle() // Directly copy static assets to the build dir. - build.AssetsCopy(buildPath, tempBuildDir) + common.CheckErr(build.AssetsCopy(buildPath, tempBuildDir)) // Run the build.js script using user local NodeJS. if NodeJSFlag { - clientBuildStr := build.NodeClient(buildPath) - staticBuildStr, allNodesStr := build.NodeDataSource(buildPath, siteConfig) - build.NodeExec(clientBuildStr, staticBuildStr, allNodesStr) + clientBuildStr, err := build.NodeClient(buildPath) + common.CheckErr(err) + staticBuildStr, allNodesStr, err := build.NodeDataSource(buildPath, siteConfig) + common.CheckErr(err) + + common.CheckErr(build.NodeExec(clientBuildStr, staticBuildStr, allNodesStr)) } else { // Prep the client SPA. - build.Client(buildPath, tempBuildDir, ejectedPath) + + common.CheckErr(build.Client(buildPath, tempBuildDir, ejectedPath)) // Build JSON from "content/" directory. - build.DataSource(buildPath, siteConfig, tempBuildDir) + common.CheckErr(build.DataSource(buildPath, siteConfig, tempBuildDir)) } // Run Gopack (custom Snowpack alternative) for ESM support. - build.Gopack(buildPath) + common.CheckErr(build.Gopack(buildPath)) if tempBuildDir != "" { // If using themes, just delete the whole build folder. - build.ThemesClean(tempBuildDir) + common.CheckErr(build.ThemesClean(tempBuildDir)) } else { // If no theme, just delete any ejectable files that the user didn't manually eject. - build.EjectClean(tempFiles, ejectedPath) + common.CheckErr(build.EjectClean(tempFiles, ejectedPath)) } } diff --git a/cmd/build/assets_copy.go b/cmd/build/assets_copy.go index bffc8822..4b8862cf 100644 --- a/cmd/build/assets_copy.go +++ b/cmd/build/assets_copy.go @@ -5,13 +5,12 @@ import ( "io" "os" "path/filepath" - "strconv" "strings" "time" ) // AssetsCopy does a direct copy of any static assets. -func AssetsCopy(buildPath string, tempBuildDir string) { +func AssetsCopy(buildPath string, tempBuildDir string) error { defer Benchmark(time.Now(), "Copying static assets into build dir") @@ -23,41 +22,46 @@ func AssetsCopy(buildPath string, tempBuildDir string) { // Exit function if "assets/" directory does not exist. if _, err := os.Stat(assetsDir); os.IsNotExist(err) { - return + return err } - assetFilesErr := filepath.Walk(assetsDir, func(assetPath string, assetFileInfo os.FileInfo, err error) error { + err := filepath.Walk(assetsDir, func(assetPath string, assetFileInfo os.FileInfo, err error) error { destPath := buildPath + "/" + strings.TrimPrefix(assetPath, tempBuildDir) if assetFileInfo.IsDir() { // Make directory if it doesn't exist. - os.MkdirAll(destPath, os.ModePerm) // Move on to next path. - return nil + return os.MkdirAll(destPath, os.ModePerm) + } from, err := os.Open(assetPath) if err != nil { - fmt.Printf("Could not open asset for copying: %s\n", err) + return fmt.Errorf("Could not open asset for copying: %w", err) + } defer from.Close() to, err := os.Create(destPath) if err != nil { - fmt.Printf("Could not create destination asset for copying: %s\n", err) + return fmt.Errorf("Could not create destination asset for copying: %w", err) + } defer to.Close() - _, fileCopyErr := io.Copy(to, from) + _, err = io.Copy(to, from) if err != nil { - fmt.Printf("Could not copy asset from source to destination: %s\n", fileCopyErr) + return fmt.Errorf("Could not copy asset from source to destination: %w", err) + } copiedSourceCounter++ return nil }) - if assetFilesErr != nil { - fmt.Printf("Could not get asset file: %s", assetFilesErr) + if err != nil { + return fmt.Errorf("Could not get asset file: %w", err) + } - Log("Number of assets copied: " + strconv.Itoa(copiedSourceCounter)) + Log(fmt.Sprintf("Number of assets copied: %d", copiedSourceCounter)) + return nil } diff --git a/cmd/build/bundle.go b/cmd/build/bundle.go index 046d9321..55e9152f 100644 --- a/cmd/build/bundle.go +++ b/cmd/build/bundle.go @@ -18,6 +18,7 @@ func Bundle() []byte { //Externals: []string{"module", "fs", "path"}, Bundle: true, }) + // error? if result.Errors != nil { fmt.Printf("Error bundling dependencies for build script: %v\n", result.Errors) } diff --git a/cmd/build/client.go b/cmd/build/client.go index 94516ce6..e38b295e 100644 --- a/cmd/build/client.go +++ b/cmd/build/client.go @@ -19,7 +19,7 @@ import ( var SSRctx *v8go.Context // Client builds the SPA. -func Client(buildPath string, tempBuildDir string, ejectedPath string) { +func Client(buildPath string, tempBuildDir string, ejectedPath string) error { defer Benchmark(time.Now(), "Compiling client SPA with Svelte") @@ -32,25 +32,42 @@ func Client(buildPath string, tempBuildDir string, ejectedPath string) { // Set up counter for logging output. compiledComponentCounter := 0 + log.Println(tempBuildDir, 3333333) // Get svelte compiler code from node_modules. - compiler, err := ioutil.ReadFile(tempBuildDir + "node_modules/svelte/compiler.js") + compiler, err := ioutil.ReadFile( + fmt.Sprintf("%snode_modules/svelte/compiler.js", tempBuildDir), + ) if err != nil { - fmt.Printf("Can't read %vnode_modules/svelte/compiler.js: %v", tempBuildDir, err) + return fmt.Errorf("Can't read %s/node_modules/svelte/compiler.js: %w", tempBuildDir, err) + } // Remove reference to 'self' that breaks v8go on line 19 of node_modules/svelte/compiler.js. compilerStr := strings.Replace(string(compiler), "self.performance.now();", "'';", 1) - ctx, _ := v8go.NewContext(nil) - _, addCompilerErr := ctx.RunScript(compilerStr, "compile_svelte") - if addCompilerErr != nil { - fmt.Printf("Could not add svelte compiler: %v\n", addCompilerErr) + ctx, err := v8go.NewContext(nil) + if err != nil { + return fmt.Errorf("Could not create Isolate: %w", err) + } + _, err = ctx.RunScript(compilerStr, "compile_svelte") + if err != nil { + return fmt.Errorf("Could not add svelte compiler: %w", err) - SSRctx, _ = v8go.NewContext(nil) + } + + SSRctx, err = v8go.NewContext(nil) + if err != nil { + return fmt.Errorf("Could not create Isolate: %w", err) + + } // Fix "ReferenceError: exports is not defined" errors on line 1319 (exports.current_component;). - SSRctx.RunScript("var exports = {};", "create_ssr") + if _, err := SSRctx.RunScript("var exports = {};", "create_ssr"); err != nil { + return err + } // Fix "TypeError: Cannot read property 'noop' of undefined" from node_modules/svelte/store/index.js. - SSRctx.RunScript("function noop(){}", "create_ssr") + if _, err := SSRctx.RunScript("function noop(){}", "create_ssr"); err != nil { + return err + } var svelteLibs = [6]string{ tempBuildDir + "node_modules/svelte/animate/index.js", @@ -63,31 +80,38 @@ func Client(buildPath string, tempBuildDir string, ejectedPath string) { for _, svelteLib := range svelteLibs { // Use v8go and add create_ssr_component() function. - createSsrComponent, npmReadErr := ioutil.ReadFile(svelteLib) - if npmReadErr != nil { - fmt.Printf("Can't read %v: %v", svelteLib, npmReadErr) + createSsrComponent, err := ioutil.ReadFile(svelteLib) + if err != nil { + return fmt.Errorf("Can't read %s: %w", svelteLib, err) + } // Fix "Cannot access 'on_destroy' before initialization" errors on line 1320 & line 1337 of node_modules/svelte/internal/index.js. createSsrStr := strings.ReplaceAll(string(createSsrComponent), "function create_ssr_component(fn) {", "function create_ssr_component(fn) {var on_destroy= {};") // Use empty noop() function created above instead of missing method. createSsrStr = strings.ReplaceAll(createSsrStr, "internal.noop", "noop") - _, createFuncErr := SSRctx.RunScript(createSsrStr, "create_ssr") + _, err = SSRctx.RunScript(createSsrStr, "create_ssr") + // `ReferenceError: require is not defined` error on build so cannot quit ... if err != nil { - fmt.Printf("Could not add create_ssr_component() func from svelte/internal: %v", createFuncErr) + fmt.Printf("Could not add create_ssr_component() func from svelte/internal: %v", err) + // return err } } // Compile router separately since it's ejected from core. - compileSvelte(ctx, SSRctx, ejectedPath+"/router.svelte", buildPath+"/spa/ejected/router.js", stylePath, tempBuildDir) + if err = (compileSvelte(ctx, SSRctx, ejectedPath+"/router.svelte", buildPath+"/spa/ejected/router.js", stylePath, tempBuildDir)); err != nil { + return err + } // Go through all file paths in the "/layout" folder. - layoutFilesErr := filepath.Walk(tempBuildDir+"layout", func(layoutPath string, layoutFileInfo os.FileInfo, err error) error { + err = filepath.Walk(tempBuildDir+"layout", func(layoutPath string, layoutFileInfo os.FileInfo, err error) error { // Create destination path. destFile := buildPath + "/spa" + strings.TrimPrefix(layoutPath, tempBuildDir+"layout") // Make sure path is a directory if layoutFileInfo.IsDir() { // Create any sub directories need for filepath. - os.MkdirAll(destFile, os.ModePerm) + if err = os.MkdirAll(destFile, os.ModePerm); err != nil { + return err + } } else { // If the file is in .svelte format, compile it to .js if filepath.Ext(layoutPath) == ".svelte" { @@ -95,7 +119,9 @@ func Client(buildPath string, tempBuildDir string, ejectedPath string) { // Replace .svelte file extension with .js. destFile = strings.TrimSuffix(destFile, filepath.Ext(destFile)) + ".js" - compileSvelte(ctx, SSRctx, layoutPath, destFile, stylePath, tempBuildDir) + if err = compileSvelte(ctx, SSRctx, layoutPath, destFile, stylePath, tempBuildDir); err != nil { + return err + } // Remove temporary theme build directory. destLayoutPath := strings.TrimPrefix(layoutPath, tempBuildDir) @@ -112,67 +138,73 @@ func Client(buildPath string, tempBuildDir string, ejectedPath string) { } return nil }) - if layoutFilesErr != nil { - fmt.Printf("Could not get layout file: %s", layoutFilesErr) + if err != nil { + return fmt.Errorf("Could not get layout file: %w", err) + } // Write layout.js to filesystem. - compWriteErr := ioutil.WriteFile(buildPath+"/spa/ejected/layout.js", []byte(allComponentsStr), os.ModePerm) - if compWriteErr != nil { - fmt.Printf("Unable to write layout.js file: %v\n", compWriteErr) + err = ioutil.WriteFile(buildPath+"/spa/ejected/layout.js", []byte(allComponentsStr), os.ModePerm) + if err != nil { + return fmt.Errorf("Unable to write layout.js file: %w", err) + } Log("Number of components compiled: " + strconv.Itoa(compiledComponentCounter)) + return nil } -func compileSvelte(ctx *v8go.Context, SSRctx *v8go.Context, layoutPath string, destFile string, stylePath string, tempBuildDir string) { +func compileSvelte(ctx *v8go.Context, SSRctx *v8go.Context, layoutPath string, + destFile string, stylePath string, tempBuildDir string) error { component, err := ioutil.ReadFile(layoutPath) if err != nil { - fmt.Printf("Can't read component: %v\n", err) + return fmt.Errorf("Can't read component: %w", err) } componentStr := string(component) // Compile component with Svelte. - ctx.RunScript("var { js, css } = svelte.compile(`"+componentStr+"`, {css: false, hydratable: true});", "compile_svelte") - + _, err = ctx.RunScript("var { js, css } = svelte.compile(`"+componentStr+"`, {css: false, hydratable: true});", "compile_svelte") + if err != nil { + return err + } // Get the JS code from the compiled result. jsCode, err := ctx.RunScript("js.code;", "compile_svelte") if err != nil { - fmt.Printf("V8go could not execute js.code: %v", err) + return fmt.Errorf("V8go could not execute js.code: %w", err) } jsBytes := []byte(jsCode.String()) - jsWriteErr := ioutil.WriteFile(destFile, jsBytes, 0755) - if jsWriteErr != nil { - fmt.Printf("Unable to write compiled client file: %v\n", jsWriteErr) + err = ioutil.WriteFile(destFile, jsBytes, 0755) + if err != nil { + return fmt.Errorf("Unable to write compiled client file: %w", err) } // Get the CSS code from the compiled result. cssCode, err := ctx.RunScript("css.code;", "compile_svelte") if err != nil { - fmt.Printf("V8go could not execute css.code: %v", err) + return fmt.Errorf("V8go could not execute css.code: %w", err) } cssStr := strings.TrimSpace(cssCode.String()) // If there is CSS, write it into the bundle.css file. if cssStr != "null" { - cssFile, WriteStyleErr := os.OpenFile(stylePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if WriteStyleErr != nil { - fmt.Printf("Could not open bundle.css for writing: %s", WriteStyleErr) + cssFile, err := os.OpenFile(stylePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("Could not open bundle.css for writing: %w", err) } defer cssFile.Close() if _, err := cssFile.WriteString(cssStr); err != nil { - log.Println(err) + return fmt.Errorf("could not write to cssStr: %w", err) } } // Get Server Side Rendered (SSR) JS. _, ssrCompileErr := ctx.RunScript("var { js: ssrJs, css: ssrCss } = svelte.compile(`"+componentStr+"`, {generate: 'ssr'});", "compile_svelte") if ssrCompileErr != nil { - fmt.Printf("V8go could not compile ssrJs.code: %v\n", ssrCompileErr) + return fmt.Errorf("V8go could not compile ssrJs.code: %w", ssrCompileErr) } ssrJsCode, err := ctx.RunScript("ssrJs.code;", "compile_svelte") if err != nil { - fmt.Printf("V8go could not get ssrJs.code value: %v\n", err) + return fmt.Errorf("V8go could not get ssrJs.code value: %w", err) } // Regex match static import statements. reStaticImport := regexp.MustCompile(`import\s((.*)\sfrom(.*);|(((.*)\n){0,})\}\sfrom(.*);)`) @@ -322,11 +354,12 @@ func compileSvelte(ctx *v8go.Context, SSRctx *v8go.Context, layoutPath string, d } // Add component to context so it can be used to render HTML in data_source.go. - _, addSSRCompErr := SSRctx.RunScript(ssrStr, "create_ssr") - if addSSRCompErr != nil { - fmt.Printf("Could not add SSR Component: %v\n", addSSRCompErr) + _, err = SSRctx.RunScript(ssrStr, "create_ssr") + if err != nil { + return fmt.Errorf("Could not add SSR Component: %w", err) } + return nil } func removeCSS(str string) string { diff --git a/cmd/build/data_source.go b/cmd/build/data_source.go index 2d8fd8b6..7ce70c74 100644 --- a/cmd/build/data_source.go +++ b/cmd/build/data_source.go @@ -3,7 +3,6 @@ package build import ( "fmt" "io/ioutil" - "log" "os" "path/filepath" "plenti/readers" @@ -26,14 +25,16 @@ type content struct { } // DataSource builds json list from "content/" directory. -func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir string) { +func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir string) error { defer Benchmark(time.Now(), "Creating data_source") Log("\nGathering data source from 'content/' folder") contentJSPath := buildPath + "/spa/ejected/content.js" - os.MkdirAll(buildPath+"/spa/ejected", os.ModePerm) + if err := os.MkdirAll(buildPath+"/spa/ejected", os.ModePerm); err != nil { + return err + } // Set up counter for logging output. contentFileCounter := 0 @@ -46,6 +47,7 @@ func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir st err := ioutil.WriteFile(contentJSPath, []byte(`const contentSource = [`), 0755) if err != nil { fmt.Printf("Unable to write content.js file: %v", err) + return err } // Go through all sub directories in "content/" folder. @@ -63,9 +65,10 @@ func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir st if fileName[:1] != "_" && fileName[:1] != "." { // Get the contents of the file. - fileContentBytes, readFileErr := ioutil.ReadFile(path) - if readFileErr != nil { - fmt.Printf("Could not read content file: %s\n", readFileErr) + fileContentBytes, err := ioutil.ReadFile(path) + if err != nil { + fmt.Printf("Could not read content file: %s\n", err) + return err } fileContentStr := string(fileContentBytes) @@ -151,7 +154,9 @@ func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir st "\"fields\": " + fileContentStr + "\n}" // Write to the content.js client data source file. - writeContentJS(contentJSPath, contentDetailsStr+",") + if err = writeContentJS(contentJSPath, contentDetailsStr+","); err != nil { + return err + } // Remove newlines, tabs, and extra space. encodedContentDetails := encodeString(contentDetailsStr) @@ -178,7 +183,8 @@ func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir st return nil }) if contentFilesErr != nil { - fmt.Printf("Could not get layout file: %s", contentFilesErr) + return fmt.Errorf("Could not get layout file: %w", contentFilesErr) + } // End the string that will be used in allContent object. @@ -186,78 +192,105 @@ func DataSource(buildPath string, siteConfig readers.SiteConfig, tempBuildDir st for _, currentContent := range allContent { - createProps(currentContent, allContentStr) + if err = createProps(currentContent, allContentStr); err != nil { + return err + } - createHTML(currentContent) + if err = createHTML(currentContent); err != nil { + return err + } - allPaginatedContent := paginate(currentContent, contentJSPath) + allPaginatedContent, err := paginate(currentContent, contentJSPath) + if err != nil { + return err + } for _, paginatedContent := range allPaginatedContent { - createProps(paginatedContent, allContentStr) - createHTML(paginatedContent) + if err = createProps(paginatedContent, allContentStr); err != nil { + return err + } + + if err = createHTML(paginatedContent); err != nil { + return err + } + } } + Log("Number of content files used: " + fmt.Sprint(contentFileCounter)) // Complete the content.js file. - writeContentJS(contentJSPath, "];\n\nexport default contentSource;") - - Log("Number of content files used: " + strconv.Itoa(contentFileCounter)) + return writeContentJS(contentJSPath, "];\n\nexport default contentSource;") } -func createProps(currentContent content, allContentStr string) { +func createProps(currentContent content, allContentStr string) error { routeSignature := "layout_content_" + currentContent.contentType + "_svelte" - _, createPropsErr := SSRctx.RunScript("var props = {route: "+routeSignature+", content: "+currentContent.contentDetails+", allContent: "+allContentStr+"};", "create_ssr") - if createPropsErr != nil { - fmt.Printf("Could not create props: %v\n", createPropsErr) + _, err := SSRctx.RunScript("var props = {route: "+routeSignature+", content: "+currentContent.contentDetails+", allContent: "+allContentStr+"};", "create_ssr") + if err != nil { + + return fmt.Errorf("Could not create props: %w", err) + } // Render the HTML with props needed for the current content. - _, renderHTMLErr := SSRctx.RunScript("var { html, css: staticCss} = layout_global_html_svelte.render(props);", "create_ssr") - if renderHTMLErr != nil { - fmt.Printf("Can't render htmlComponent: %v\n", renderHTMLErr) + _, err = SSRctx.RunScript("var { html, css: staticCss} = layout_global_html_svelte.render(props);", "create_ssr") + if err != nil { + return fmt.Errorf("Can't render htmlComponent: %w", err) + } + return nil } -func createHTML(currentContent content) { +func createHTML(currentContent content) error { // Get the rendered HTML from v8go. renderedHTML, err := SSRctx.RunScript("html;", "create_ssr") if err != nil { - fmt.Printf("V8go could not execute js default: %v\n", err) + return fmt.Errorf("V8go could not execute js default: %w", err) + } // Get the string value of the static HTML. renderedHTMLStr := renderedHTML.String() // Convert the string to byte array that can be written to file system. htmlBytes := []byte(renderedHTMLStr) // Create any folders need to write file. - os.MkdirAll(strings.TrimSuffix(currentContent.contentDest, "/index.html"), os.ModePerm) + if err := os.MkdirAll(strings.TrimSuffix(currentContent.contentDest, "/index.html"), os.ModePerm); err != nil { + return fmt.Errorf("couldn't create dirs in createHTML: %w", err) + } // Write static HTML to the filesystem. - htmlWriteErr := ioutil.WriteFile(currentContent.contentDest, htmlBytes, 0755) - if htmlWriteErr != nil { - fmt.Printf("Unable to write SSR file: %v\n", htmlWriteErr) + err = ioutil.WriteFile(currentContent.contentDest, htmlBytes, 0755) + if err != nil { + return fmt.Errorf("unable to write SSR file: %w", err) } + return nil } -func paginate(currentContent content, contentJSPath string) []content { +func paginate(currentContent content, contentJSPath string) ([]content, error) { paginatedContent, _ := getPagination() + var err error allNewContent := []content{} // Loop through all :paginate() replacements found in config file. for _, pager := range paginatedContent { // Check if the config file specifies pagination for this Type. if len(pager.paginationVars) > 0 && pager.contentType == currentContent.contentType { // Increment the pager. - allNewContent = incrementPager(pager.paginationVars, currentContent, contentJSPath, allNewContent) + allNewContent, err = incrementPager(pager.paginationVars, currentContent, contentJSPath, allNewContent) + if err != nil { + return nil, err + } } } - return allNewContent + return allNewContent, err } -func incrementPager(paginationVars []string, currentContent content, contentJSPath string, allNewContent []content) []content { +func incrementPager(paginationVars []string, currentContent content, contentJSPath string, allNewContent []content) ([]content, error) { // Pop first item from the list. paginationVar, paginationVars := paginationVars[0], paginationVars[1:] // Copy the current content so we can increment the pager. newContent := currentContent // Get the number of pages for the pager. - totalPagesInt := getTotalPages(paginationVar) + totalPagesInt, err := getTotalPages(paginationVar) + if err != nil { + return nil, err + } // Loop through total number of pages for current pager. for i := 1; i <= totalPagesInt; i++ { // Convert page number to a string that can be used in a path. @@ -275,7 +308,12 @@ func incrementPager(paginationVars []string, currentContent content, contentJSPa // Check if there are more pagers for the route override. if len(paginationVars) > 0 { // Recursively call func to increment second pager. - allNewContent = incrementPager(paginationVars, newContent, contentJSPath, allNewContent) + // todo: a better approach + allNewContentTmp, err := incrementPager(paginationVars, newContent, contentJSPath, allNewContent) + if err != nil { + return nil, err + } + allNewContent = allNewContentTmp // Remove first item in the array to move to the next number in the first pager. newContent.contentPagerNums = newContent.contentPagerNums[1:] // Continue because you don't want to complete the loop with a partially updated path (we have more pagers!). @@ -299,40 +337,45 @@ func incrementPager(paginationVars []string, currentContent content, contentJSPa "\"fields\": " + newContent.contentFields + "\n}" // Add paginated entries to content.js file. - writeContentJS(contentJSPath, newContent.contentDetails+",") + if err := writeContentJS(contentJSPath, newContent.contentDetails+","); err != nil { + return nil, err + } // Add to array of content for creating paginated static HTML fallbacks. allNewContent = append(allNewContent, newContent) // Remove last number from array to get next page in current pager. newContent.contentPagerNums = newContent.contentPagerNums[:len(newContent.contentPagerNums)-1] } - return allNewContent + return allNewContent, nil } -func getTotalPages(paginationVar string) int { - totalPages, getLocalVarErr := SSRctx.RunScript("plenti_global_pager_"+paginationVar, "create_ssr") - if getLocalVarErr != nil { - fmt.Printf("Could not get value of '%v' used in pager: %v\n", paginationVar, getLocalVarErr) +func getTotalPages(paginationVar string) (int, error) { + totalPages, err := SSRctx.RunScript("plenti_global_pager_"+paginationVar, "create_ssr") + if err != nil { + return 0, fmt.Errorf("Could not get value of '%v' used in pager: %w", paginationVar, err) } // Convert string total page value to integer. - totalPagesInt, strToIntErr := strconv.Atoi(totalPages.String()) - if strToIntErr != nil { - fmt.Printf("Can't convert pager value '%v' to an integer: %v\n", totalPages.String(), strToIntErr) + totalPagesInt, err := strconv.Atoi(totalPages.String()) + if err != nil { + return 0, fmt.Errorf("Can't convert pager value '%s' to an integer: %w", totalPages.String(), err) } - return totalPagesInt + return totalPagesInt, nil } -func writeContentJS(contentJSPath string, contentDetailsStr string) { +func writeContentJS(contentJSPath string, contentDetailsStr string) error { // Create new content.js file if it doesn't already exist, or add to it if it does. - contentJSFile, openContentJSErr := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if openContentJSErr != nil { - fmt.Printf("Could not open content.js for writing: %s", openContentJSErr) + contentJSFile, err := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("could not open content.js for writing: %w", err) } // Write to the file with info from current file in "/content" folder. defer contentJSFile.Close() if _, err := contentJSFile.WriteString(contentDetailsStr); err != nil { - log.Println(err) + + return fmt.Errorf("could not write to file %s: %w", contentJSPath, err) + } + return nil } func encodeString(encodedStr string) string { diff --git a/cmd/build/eject_clean.go b/cmd/build/eject_clean.go index 3f799085..163eb594 100644 --- a/cmd/build/eject_clean.go +++ b/cmd/build/eject_clean.go @@ -7,7 +7,7 @@ import ( ) // EjectClean removes core files that hadn't been ejected to project filesystem. -func EjectClean(tempFiles []string, ejectedPath string) { +func EjectClean(tempFiles []string, ejectedPath string) error { defer Benchmark(time.Now(), "Cleaning up non-ejected core files") @@ -15,13 +15,18 @@ func EjectClean(tempFiles []string, ejectedPath string) { for _, file := range tempFiles { Log("Removing temp file '" + file + "'") - os.Remove(file) + if err := os.Remove(file); err != nil { + return err + } } // If no files were ejected by user, clean up the directory after build. if len(tempFiles) == len(generated.Ejected) { Log("Removing the ejected directory.") - os.Remove(ejectedPath) + if err := os.Remove(ejectedPath); err != nil { + return err + } } + return nil } diff --git a/cmd/build/eject_copy.go b/cmd/build/eject_copy.go index 317eca90..9077499d 100644 --- a/cmd/build/eject_copy.go +++ b/cmd/build/eject_copy.go @@ -5,13 +5,12 @@ import ( "io" "os" "path/filepath" - "strconv" "strings" "time" ) // EjectCopy does a direct copy of any ejectable js files needed in spa build dir. -func EjectCopy(buildPath string, tempBuildDir string, ejectedDir string) { +func EjectCopy(buildPath string, tempBuildDir string, ejectedDir string) error { defer Benchmark(time.Now(), "Copying ejectable core files for build") @@ -35,23 +34,25 @@ func EjectCopy(buildPath string, tempBuildDir string, ejectedDir string) { if filepath.Ext(ejectPath) == ".js" && !excluded { destPath := buildPath + "/spa/" - os.MkdirAll(destPath+strings.TrimPrefix(ejectedDir, tempBuildDir), os.ModePerm) + if err := os.MkdirAll(destPath+strings.TrimPrefix(ejectedDir, tempBuildDir), os.ModePerm); err != nil { + return err + } from, err := os.Open(ejectPath) if err != nil { - fmt.Printf("Could not open source .js file for copying: %s\n", err) + return fmt.Errorf("Could not open source .js file for copying: %w", err) } defer from.Close() to, err := os.Create(destPath + strings.TrimPrefix(ejectPath, tempBuildDir)) if err != nil { - fmt.Printf("Could not create destination .js file for copying: %s\n", err) + return fmt.Errorf("Could not create destination .js file for copying: %w", err) } defer to.Close() - _, fileCopyErr := io.Copy(to, from) + _, err = io.Copy(to, from) if err != nil { - fmt.Printf("Could not copy .js from source to destination: %s\n", fileCopyErr) + return fmt.Errorf("Could not copy .js from source to destination: %w", err) } copiedSourceCounter++ @@ -59,9 +60,10 @@ func EjectCopy(buildPath string, tempBuildDir string, ejectedDir string) { return nil }) if ejectedFilesErr != nil { - fmt.Printf("Could not get ejectable file: %s", ejectedFilesErr) + return fmt.Errorf("Could not get ejectable file: %w", ejectedFilesErr) } - Log("Number of ejectable core files copied: " + strconv.Itoa(copiedSourceCounter)) + Log(fmt.Sprintf("Number of ejectable core files copied: %d\n", copiedSourceCounter)) + return nil } diff --git a/cmd/build/eject_temp.go b/cmd/build/eject_temp.go index 3e4bbe8c..19e493a7 100644 --- a/cmd/build/eject_temp.go +++ b/cmd/build/eject_temp.go @@ -10,7 +10,7 @@ import ( ) // EjectTemp temporarily writes ejectable core files to project filesystem. -func EjectTemp(tempBuildDir string) ([]string, string) { +func EjectTemp(tempBuildDir string) ([]string, string, error) { defer Benchmark(time.Now(), "Creating non-ejected core files for build") @@ -24,21 +24,23 @@ func EjectTemp(tempBuildDir string) ([]string, string) { for file, content := range generated.Ejected { filePath := ejectedPath + file // Create the directories needed for the current file - os.MkdirAll(filepath.Dir(filePath), os.ModePerm) + if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { + return nil, "", err + } if _, ejectedFileExistsErr := os.Stat(filePath); os.IsNotExist(ejectedFileExistsErr) { Log("Temp writing '" + file + "' file.") // Create the current default file - writeCoreFileErr := ioutil.WriteFile(filePath, content, os.ModePerm) - if writeCoreFileErr != nil { - fmt.Printf("Unable to write ejected core file: %v\n", writeCoreFileErr) - } else { - tempFiles = append(tempFiles, filePath) + err := ioutil.WriteFile(filePath, content, os.ModePerm) + if err != nil { + return nil, "", fmt.Errorf("Unable to write ejected core file: %w", err) } + tempFiles = append(tempFiles, filePath) + } else { Log("File '" + file + "' has been ejected already, skipping temp write.") } } - return tempFiles, ejectedPath + return tempFiles, ejectedPath, nil } diff --git a/cmd/build/gopack.go b/cmd/build/gopack.go index 33146bd2..e91efc74 100644 --- a/cmd/build/gopack.go +++ b/cmd/build/gopack.go @@ -14,7 +14,7 @@ import ( ) // Gopack ensures ESM support for NPM dependencies. -func Gopack(buildPath string) { +func Gopack(buildPath string) error { defer Benchmark(time.Now(), "Running Gopack") @@ -31,38 +31,41 @@ func Gopack(buildPath string) { if !moduleFileInfo.IsDir() && filepath.Ext(modulePath) == ".mjs" { from, err := os.Open(modulePath) if err != nil { - fmt.Printf("Could not open source .mjs file for copying: %s\n", err) + return fmt.Errorf("Could not open source .mjs file for copying: %w", err) } defer from.Close() // Remove "node_modules" from path and add "web_modules". modulePath = gopackDir + strings.Replace(modulePath, "node_modules", "", 1) // Create any subdirectories need to write file to "web_modules" destination. - os.MkdirAll(filepath.Dir(modulePath), os.ModePerm) + if err = os.MkdirAll(filepath.Dir(modulePath), os.ModePerm); err != nil { + return err + } // Change the .mjs file extension to .js. modulePath = strings.TrimSuffix(modulePath, filepath.Ext(modulePath)) + ".js" to, err := os.Create(modulePath) if err != nil { - fmt.Printf("Could not create destination .mjs file for copying: %s\n", err) + return fmt.Errorf("Could not create destination .mjs file for copying: %w", err) } defer to.Close() - _, fileCopyErr := io.Copy(to, from) + _, err = io.Copy(to, from) if err != nil { - fmt.Printf("Could not copy .mjs from source to destination: %s\n", fileCopyErr) + return fmt.Errorf("Could not copy .mjs from source to destination: %w", err) } } return nil }) if nodeModuleErr != nil { - fmt.Printf("Could not get node module: %s", nodeModuleErr) + return fmt.Errorf("Could not get node module: %w", nodeModuleErr) } + } convertErr := filepath.Walk(buildPath+"/spa", func(convertPath string, convertFileInfo os.FileInfo, err error) error { if !convertFileInfo.IsDir() && filepath.Ext(convertPath) == ".js" { contentBytes, err := ioutil.ReadFile(convertPath) if err != nil { - fmt.Printf("Could not read file to convert to esm: %s\n", err) + return fmt.Errorf("Could not read file to convert to esm: %w", err) } // Match dynamic import statments, e.g. import("") or import(''). @@ -112,6 +115,7 @@ func Gopack(buildPath string) { } // If the import/export points to a path that exists and it is a .js file (imports must reference the file specifically) then we don't need to convert anything. if _, pathExistsErr := os.Stat(fullPath); !os.IsNotExist(pathExistsErr) && filepath.Ext(fullPath) == ".js" { + // error? Log("Skipping converting import/export in " + convertPath + " because import/export is valid: " + string(staticStatement)) } else if pathStr[:1] == "." { // If the import/export path starts with a dot (.) or double dot (..) look for the file it's trying to import from this relative path. @@ -123,7 +127,7 @@ func Gopack(buildPath string) { return nil }) if findRelativePathErr != nil { - fmt.Printf("Could not find related .mjs file: %s", findRelativePathErr) + return fmt.Errorf("Could not find related .mjs file: %w", findRelativePathErr) } } else { // A named import/export is being used, look for this in "web_modules/" dir. @@ -141,7 +145,7 @@ func Gopack(buildPath string) { return nil }) if findNamedPathErr != nil { - fmt.Printf("Could not find related .js file from named import: %s", findNamedPathErr) + return fmt.Errorf("Could not find related .js file from named import: %w", findNamedPathErr) } } } @@ -159,16 +163,17 @@ func Gopack(buildPath string) { } } // Overwrite the old file with the new content that contains the updated import path. - overwritePathErr := ioutil.WriteFile(convertPath, contentBytes, 0644) - if overwritePathErr != nil { - fmt.Printf("Could not overwite %s with new import: %s", convertPath, overwritePathErr) + err = ioutil.WriteFile(convertPath, contentBytes, 0644) + if err != nil { + return fmt.Errorf("Could not overwite %s with new import: %w", convertPath, err) } } return nil }) if convertErr != nil { - fmt.Printf("Could not convert file to support esm: %s", convertErr) + return fmt.Errorf("Could not convert file to support esm: %w", convertErr) } + return nil } diff --git a/cmd/build/node_client.go b/cmd/build/node_client.go index bb2a9178..da02ac0d 100644 --- a/cmd/build/node_client.go +++ b/cmd/build/node_client.go @@ -10,7 +10,7 @@ import ( ) // NodeClient preps the client SPA for execution via NodeJS (NOTE: This is legacy functionality). -func NodeClient(buildPath string) string { +func NodeClient(buildPath string) (string, error) { defer Benchmark(time.Now(), "Prepping client SPA data") @@ -31,7 +31,9 @@ func NodeClient(buildPath string) string { // Make sure path is a directory if layoutFileInfo.IsDir() { // Create any sub directories need for filepath. - os.MkdirAll(destFile, os.ModePerm) + if err = os.MkdirAll(destFile, os.ModePerm); err != nil { + return fmt.Errorf("cannot create sub directories need for filepath %s: %w", destFile, err) + } } else { // If the file is in .svelte format, compile it to .js if filepath.Ext(layoutPath) == ".svelte" { @@ -49,7 +51,7 @@ func NodeClient(buildPath string) string { return nil }) if layoutFilesErr != nil { - fmt.Printf("Could not get layout file: %s", layoutFilesErr) + return "", fmt.Errorf("Could not get layout file: %w", layoutFilesErr) } // Get router from ejected core. NOTE if you remove this, trim the trailing comma below. @@ -61,6 +63,6 @@ func NodeClient(buildPath string) string { Log("Number of components to be compiled: " + strconv.Itoa(compiledComponentCounter)) - return clientBuildStr + return clientBuildStr, nil } diff --git a/cmd/build/node_data_source.go b/cmd/build/node_data_source.go index 83dfb104..c74be0ea 100644 --- a/cmd/build/node_data_source.go +++ b/cmd/build/node_data_source.go @@ -3,25 +3,25 @@ package build import ( "fmt" "io/ioutil" - "log" "os" "path/filepath" "plenti/readers" "regexp" - "strconv" "strings" "time" ) // NodeDataSource gathers data json from "content/" directory to use in NodeJS build (NOTE: This is legacy). -func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, string) { +func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, string, error) { defer Benchmark(time.Now(), "Creating data_source") Log("\nGathering data source from 'content/' folder") contentJSPath := buildPath + "/spa/ejected/content.js" - os.MkdirAll(buildPath+"/spa/ejected", os.ModePerm) + if err := os.MkdirAll(buildPath+"/spa/ejected", os.ModePerm); err != nil { + return "", "", err + } // Set up counter for logging output. contentFileCounter := 0 @@ -48,9 +48,10 @@ func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, st if fileName[:1] != "_" && fileName[:1] != "." { // Get the contents of the file. - fileContentBytes, readFileErr := ioutil.ReadFile(path) - if readFileErr != nil { - fmt.Printf("Could not read content file: %s\n", readFileErr) + fileContentBytes, err := ioutil.ReadFile(path) + if err != nil { + fmt.Printf("Could not read content file: %s\n", err) + return err } fileContentStr := string(fileContentBytes) @@ -122,14 +123,14 @@ func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, st "\"fields\": " + fileContentStr + "\n}" // Create new content.js file if it doesn't already exist, or add to it if it does. - contentJSFile, openContentJSErr := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if openContentJSErr != nil { - fmt.Printf("Could not open content.js for writing: %s", openContentJSErr) + contentJSFile, err := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + fmt.Printf("Could not open content.js for writing: %s", err) } // Write to the file with info from current file in "/content" folder. defer contentJSFile.Close() if _, err := contentJSFile.WriteString(contentDetailsStr + ","); err != nil { - log.Println(err) + return err } // Need to encode html so it can be send as string to NodeJS in exec.Command. @@ -152,6 +153,7 @@ func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, st // Do not add a content source without a corresponding template to the build string. if _, noEndpointErr := os.Stat(componentPath); os.IsNotExist(noEndpointErr) { // The componentPath does not exist, go to the next content source. + // this is/should be an error? return nil } // Add to list of data_source files for creating static HTML. @@ -169,21 +171,22 @@ func NodeDataSource(buildPath string, siteConfig readers.SiteConfig) (string, st } // Complete the content.js file. - contentJSFile, openContentJSErr := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if openContentJSErr != nil { - fmt.Printf("Could not open content.js for writing: %s", openContentJSErr) + contentJSFile, err := os.OpenFile(contentJSPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + fmt.Printf("Could not open content.js for writing: %s", err) + return "", "", err } defer contentJSFile.Close() if _, err := contentJSFile.WriteString("];\n\nexport default contentSource;"); err != nil { - log.Println(err) + return "", "", err } // End the string that will be sent to nodejs for compiling. staticBuildStr = strings.TrimSuffix(staticBuildStr, ",") + "]" allContentStr = strings.TrimSuffix(allContentStr, ",") + "]" - Log("Number of content files used: " + strconv.Itoa(contentFileCounter)) + Log(fmt.Sprintf("Number of content files used: %d", contentFileCounter)) - return staticBuildStr, allContentStr + return staticBuildStr, allContentStr, nil } diff --git a/cmd/build/node_exec.go b/cmd/build/node_exec.go index e90e4437..63fc2fcc 100644 --- a/cmd/build/node_exec.go +++ b/cmd/build/node_exec.go @@ -7,13 +7,13 @@ import ( ) // NodeExec runs a build script written in NodeJS that compiles svelte. -func NodeExec(clientBuildStr string, staticBuildStr string, allNodesStr string) { +func NodeExec(clientBuildStr string, staticBuildStr string, allNodesStr string) error { defer Benchmark(time.Now(), "Compiling components and creating static HTML via NodeJS") svelteBuild := exec.Command("node", "ejected/build.js", clientBuildStr, staticBuildStr, allNodesStr) svelteBuild.Stdout = os.Stdout svelteBuild.Stderr = os.Stderr - svelteBuild.Run() + return svelteBuild.Run() } diff --git a/cmd/build/npm_defaults.go b/cmd/build/npm_defaults.go index 4a8360bf..c77a870b 100644 --- a/cmd/build/npm_defaults.go +++ b/cmd/build/npm_defaults.go @@ -10,7 +10,7 @@ import ( ) // NpmDefaults creates the node_modules folder with core defaults if it doesn't already exist. -func NpmDefaults(tempBuildDir string) { +func NpmDefaults(tempBuildDir string) error { defer Benchmark(time.Now(), "Setting up core NPM packages") @@ -23,13 +23,15 @@ func NpmDefaults(tempBuildDir string) { // Make file relative to where CLI is executed file = destPath + "/" + file // Create the directories needed for the current file - os.MkdirAll(filepath.Dir(file), os.ModePerm) + if err = os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil { + return fmt.Errorf("Unable to MkdirAll in NpmDefaults: %w", err) + } // Create the current default file err := ioutil.WriteFile(file, content, os.ModePerm) if err != nil { - fmt.Printf("Unable to write npm dependency file: %v", err) + return fmt.Errorf("Unable to write npm dependency file: %w", err) } } } - + return nil } diff --git a/cmd/build/themes_clean.go b/cmd/build/themes_clean.go index 74e75927..59eb403b 100644 --- a/cmd/build/themes_clean.go +++ b/cmd/build/themes_clean.go @@ -6,11 +6,11 @@ import ( ) // ThemesClean removes temporary build directory used to compile themes. -func ThemesClean(tempBuildDir string) { +func ThemesClean(tempBuildDir string) error { defer Benchmark(time.Now(), "Cleaning up temporary theme directory") Log("Removing the '" + tempBuildDir + "' temporary themes directory") - os.RemoveAll(tempBuildDir) + return os.RemoveAll(tempBuildDir) } diff --git a/cmd/build/themes_copy.go b/cmd/build/themes_copy.go index 691678a7..279d3196 100644 --- a/cmd/build/themes_copy.go +++ b/cmd/build/themes_copy.go @@ -12,7 +12,7 @@ import ( ) // ThemesCopy copies nested themes into a temporary working directory. -func ThemesCopy(theme string, themeOptions readers.ThemeOptions) string { +func ThemesCopy(theme string, themeOptions readers.ThemeOptions) (string, error) { defer Benchmark(time.Now(), "Building themes") @@ -24,7 +24,10 @@ func ThemesCopy(theme string, themeOptions readers.ThemeOptions) string { // Look for options (like excluded folders) in theme. nestedThemeOptions := siteConfig.ThemeConfig[nestedTheme] // Recursively run merge on nested theme. - ThemesCopy(theme+"/themes/"+nestedTheme, nestedThemeOptions) + _, err := ThemesCopy(theme+"/themes/"+nestedTheme, nestedThemeOptions) + if err != nil { + return "", err + } } // Name of temporary directory to run build inside. @@ -57,7 +60,7 @@ func ThemesCopy(theme string, themeOptions readers.ThemeOptions) string { // Read the source theme file. from, err := os.Open(themeFilePath) if err != nil { - fmt.Printf("Could not open theme file for copying: %s\n", err) + return fmt.Errorf("Could not open theme file for copying: %w", err) } defer from.Close() @@ -67,20 +70,19 @@ func ThemesCopy(theme string, themeOptions readers.ThemeOptions) string { // Create the folders needed to write files to tempDir. if themeFileInfo.IsDir() { // Make directory if it doesn't exist. - os.MkdirAll(destPath, os.ModePerm) // Move on to next path. - return nil + return os.MkdirAll(destPath, os.ModePerm) } to, err := os.Create(destPath) if err != nil { - fmt.Printf("Could not create destination theme file for copying: %s\n", err) + return fmt.Errorf("Could not create destination theme file for copying: %w", err) } defer to.Close() _, fileCopyErr := io.Copy(to, from) if err != nil { - fmt.Printf("Could not copy theme file from source to destination: %s\n", fileCopyErr) + return fmt.Errorf("Could not copy theme file from source to destination: %w", fileCopyErr) } copiedThemeFileCounter++ @@ -88,11 +90,11 @@ func ThemesCopy(theme string, themeOptions readers.ThemeOptions) string { return nil }) if themeFilesErr != nil { - fmt.Printf("Could not get theme file: %s", themeFilesErr) + return "", fmt.Errorf("Could not get theme file: %w", themeFilesErr) } Log("Number of theme files copied: " + strconv.Itoa(copiedThemeFileCounter)) - return tempBuildDir + return tempBuildDir, nil } diff --git a/cmd/build/themes_merge.go b/cmd/build/themes_merge.go index 178a05c8..fe225106 100644 --- a/cmd/build/themes_merge.go +++ b/cmd/build/themes_merge.go @@ -11,7 +11,7 @@ import ( ) // ThemesMerge combines any nested themes with the current project. -func ThemesMerge(tempBuildDir string, buildDir string) { +func ThemesMerge(tempBuildDir string, buildDir string) error { defer Benchmark(time.Now(), "Merging themes with your project") @@ -41,7 +41,7 @@ func ThemesMerge(tempBuildDir string, buildDir string) { // Read the source project file. from, err := os.Open(projectFilePath) if err != nil { - fmt.Printf("Could not open project file for copying: %s\n", err) + return fmt.Errorf("Could not open project file for copying: %w", err) } defer from.Close() @@ -51,20 +51,19 @@ func ThemesMerge(tempBuildDir string, buildDir string) { // Create the folders needed to write files to tempDir. if projectFileInfo.IsDir() { // Make directory if it doesn't exist. - os.MkdirAll(destPath, os.ModePerm) - // Move on to next path. - return nil + return os.MkdirAll(destPath, os.ModePerm) + } to, err := os.Create(destPath) if err != nil { - fmt.Printf("Could not create destination project file for copying: %s\n", err) + return fmt.Errorf("Could not create destination project file for copying: %w", err) } defer to.Close() _, fileCopyErr := io.Copy(to, from) if err != nil { - fmt.Printf("Could not copy project file from source to destination: %s\n", fileCopyErr) + return fmt.Errorf("Could not copy project file from source to destination: %w", fileCopyErr) } copiedProjectFileCounter++ @@ -72,9 +71,10 @@ func ThemesMerge(tempBuildDir string, buildDir string) { return nil }) if themeFilesErr != nil { - fmt.Printf("Could not get project file: %s", themeFilesErr) + return fmt.Errorf("Could not get project file: %w", themeFilesErr) } Log("Number of project files copied: " + strconv.Itoa(copiedProjectFileCounter)) + return nil } diff --git a/cmd/eject.go b/cmd/eject.go index 403c79ee..1a8e497e 100644 --- a/cmd/eject.go +++ b/cmd/eject.go @@ -3,9 +3,9 @@ package cmd import ( "fmt" "io/ioutil" - "log" "os" "path/filepath" + "plenti/common" "plenti/generated" "github.com/manifoldco/promptui" @@ -41,7 +41,7 @@ automatically).`, for _, file := range allEjectableFiles { filePath := "ejected" + file content := generated.Ejected[file] - ejectFile(filePath, content) + common.CheckErr(ejectFile(filePath, content)) } return } @@ -60,22 +60,21 @@ automatically).`, Label: "If ejected, this file will no longer receive updates and we can't gaurantee Plenti will work with your edits. Are you sure you want to proceed?", Items: []string{"Yes", "No"}, } - _, confirmed, confirmErr := confirmPrompt.Run() - if confirmErr != nil { - fmt.Printf("Prompt failed %v\n", confirmErr) + _, confirmed, err := confirmPrompt.Run() + if err != nil { + fmt.Printf("Prompt failed %v\n", err) return } if confirmed == "Yes" { filePath := "ejected" + result content := generated.Ejected[result] - ejectFile(filePath, content) - } - if confirmed == "No" { + common.CheckErr(ejectFile(filePath, content)) + } else if confirmed == "No" { fmt.Println("No file was ejected.") } } if len(args) >= 1 { - fmt.Printf("Attempting to eject each file listed\n") + fmt.Println("Attempting to eject each file listed") for _, arg := range args { arg = "/" + arg fileExists := false @@ -91,7 +90,7 @@ automatically).`, } filePath := "ejected" + arg content := generated.Ejected[arg] - ejectFile(filePath, content) + common.CheckErr(ejectFile(filePath, content)) } } @@ -113,29 +112,30 @@ func init() { ejectCmd.Flags().BoolVarP(&EjectAll, "all", "a", false, "Eject all core files") } -func ejectFile(filePath string, content []byte) { - if _, fileExistsErr := os.Stat(filePath); fileExistsErr == nil { +func ejectFile(filePath string, content []byte) error { + if _, err := os.Stat(filePath); err == nil { overwritePrompt := promptui.Select{ Label: "'" + filePath + "' has already been ejected, do you want to overwrite it?", Items: []string{"Yes", "No"}, } - _, overwrite, overwriteErr := overwritePrompt.Run() - if overwriteErr != nil { - log.Fatalf("Prompt failed %v\n", overwriteErr) + _, overwrite, err := overwritePrompt.Run() + if err != nil { + return fmt.Errorf("Prompt failed %w", err) } if overwrite == "No" { - return + return nil } } if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil { - log.Fatalf("Unable to create path(s) %s: %v\n", filepath.Dir(filePath), err) + return fmt.Errorf("Unable to create path(s) %s: %w", filepath.Dir(filePath), err) } if err := ioutil.WriteFile(filePath, content, os.ModePerm); err != nil { - log.Fatalf("Unable to write file: %v\n", err) + return fmt.Errorf("Unable to write file: %w", err) } fmt.Printf("Ejected %s\n", filePath) + return nil } diff --git a/cmd/root.go b/cmd/root.go index 6ce38587..fb5206cb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,10 +4,10 @@ import ( "fmt" "log" "os" + "plenti/common" "github.com/spf13/cobra" - homedir "github.com/mitchellh/go-homedir" "github.com/spf13/viper" ) @@ -34,7 +34,7 @@ Learn more at https://plenti.co`, if versionFlag { fmt.Println(Version) } else { - cmd.Help() + common.CheckErr(cmd.Help()) } }, } @@ -69,12 +69,18 @@ func initConfig() { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { - // Find home directory. - home, err := homedir.Dir() + // there since go 1.12. ok? + home, err := os.UserHomeDir() if err != nil { log.Fatal(err) } + // // Find home directory. + // home, err := homedir.Dir() + // if err != nil { + // log.Fatal(err) + + // } // Search config in home directory with name ".plenti" (without extension). viper.AddConfigPath(home) diff --git a/cmd/serve.go b/cmd/serve.go index 2c8ea3c1..0f97d88a 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -5,13 +5,9 @@ import ( "log" "net/http" "os" - "path/filepath" - "time" - "plenti/cmd/build" "plenti/readers" - "github.com/fsnotify/fsnotify" "github.com/spf13/cobra" ) @@ -60,6 +56,9 @@ You can also set a different port in your site config file.`, fmt.Printf("The \"%v\" build directory does not exist, check your plenti.json file.\n", buildDir) log.Fatal(err) } + // Watch filesystem for changes. + gowatch(buildDir) + fmt.Printf("\nServing site from your \"%v\" directory.\n", buildDir) // Point to folder containing the built site @@ -69,15 +68,9 @@ You can also set a different port in your site config file.`, // Check flags and config for local server port port := setPort(siteConfig) - // Watch filesystem for changes. - go Watch(buildDir) - // Start the webserver fmt.Printf("Visit your site at http://localhost:%v/\n", port) - err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) - if err != nil { - log.Fatal(err) - } + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) }, } @@ -101,103 +94,3 @@ func init() { serveCmd.Flags().BoolVarP(&VerboseFlag, "verbose", "v", false, "show log messages") serveCmd.Flags().BoolVarP(&BenchmarkFlag, "benchmark", "b", false, "display build time statistics") } - -var watcher *fsnotify.Watcher - -// Watch looks for updates to filesystem to prompt a site rebuild. -func Watch(buildPath string) { - - // Creates a new file watcher. - watcher, _ = fsnotify.NewWatcher() - defer watcher.Close() - - // Watch specific directories for changes (only if they exist). - if _, err := os.Stat("content"); !os.IsNotExist(err) { - if err := filepath.Walk("content", watchDir(buildPath)); err != nil { - fmt.Println("Error watching 'content/' folder for changes: ", err) - } - } - if _, err := os.Stat("layout"); !os.IsNotExist(err) { - if err := filepath.Walk("layout", watchDir(buildPath)); err != nil { - fmt.Println("Error watching 'layout/' folder for changes: ", err) - } - } - if _, err := os.Stat("assets"); !os.IsNotExist(err) { - if err := filepath.Walk("assets", watchDir(buildPath)); err != nil { - fmt.Println("Error watching 'assets/' folder for changes: ", err) - } - } - watcher.Add("plenti.json") - watcher.Add("package.json") - - done := make(chan bool) - - // Set delay for batching events. - ticker := time.NewTicker(300 * time.Millisecond) - // Create array for storing double firing events (happens when saving files in some text editors). - events := make([]fsnotify.Event, 0) - - go func() { - for { - select { - // Watch for events. - case event := <-watcher.Events: - // Don't rebuild when build dir is added or deleted. - if event.Name != "./"+buildPath { - // Add current event to array for batching. - events = append(events, event) - } - case <-ticker.C: - // Checks on set interval if there are events. - if len(events) > 0 { - // Display messages for each events in batch. - for _, event := range events { - if event.Op&fsnotify.Create == fsnotify.Create { - build.Log("File create detected: " + event.String()) - watcher.Add(event.Name) - build.Log("Now watching " + event.Name) - } - if event.Op&fsnotify.Write == fsnotify.Write { - build.Log("File write detected: " + event.String()) - } - if event.Op&fsnotify.Remove == fsnotify.Remove { - build.Log("File delete detected: " + event.String()) - } - if event.Op&fsnotify.Rename == fsnotify.Rename { - build.Log("File rename detected: " + event.String()) - } - } - // Rebuild only one time for all batched events. - Build() - // Empty the batch array. - events = make([]fsnotify.Event, 0) - - } - - // Watch for errors. - case err := <-watcher.Errors: - if err != nil { - fmt.Printf("\nFile watching error: %s\n", err) - } - } - } - }() - - <-done -} - -// Closure that enables passing buildPath as arg to callback. -func watchDir(buildPath string) filepath.WalkFunc { - // Callback for walk func: searches for directories to add watchers to. - return func(path string, fi os.FileInfo, err error) error { - // Skip the "public" build dir to avoid infinite loops. - if fi.IsDir() && fi.Name() == buildPath { - return filepath.SkipDir - } - // Add watchers only to nested directory. - if fi.Mode().IsDir() { - return watcher.Add(path) - } - return nil - } -} diff --git a/cmd/theme_add.go b/cmd/theme_add.go index 9fff6ce9..78028fc3 100644 --- a/cmd/theme_add.go +++ b/cmd/theme_add.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os" + "plenti/common" "plenti/readers" "plenti/writers" "strings" @@ -113,7 +114,7 @@ To use https://plenti.co as a theme for example, run: plenti new theme git@githu siteConfig.ThemeConfig[repoName] = *themeOptions // Update the config file on the filesystem. - writers.SetSiteConfig(siteConfig, configPath) + common.CheckErr(writers.SetSiteConfig(siteConfig, configPath)) }, } diff --git a/cmd/theme_disable.go b/cmd/theme_disable.go index 63fc1c7c..04889312 100644 --- a/cmd/theme_disable.go +++ b/cmd/theme_disable.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "fmt" + "plenti/common" "plenti/readers" "plenti/writers" @@ -47,7 +48,7 @@ will no longer inherit assets, content, and layout from this theme. } siteConfig.Theme = "" // Update the config file on the filesystem. - writers.SetSiteConfig(siteConfig, configPath) + common.CheckErr(writers.SetSiteConfig(siteConfig, configPath)) }, } diff --git a/cmd/theme_enable.go b/cmd/theme_enable.go index 1c0620de..d9003a4a 100644 --- a/cmd/theme_enable.go +++ b/cmd/theme_enable.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "plenti/common" "plenti/readers" "plenti/writers" @@ -42,7 +43,7 @@ and layout from the theme you enabled. siteConfig.Theme = repoName // Update the config file on the filesystem. - writers.SetSiteConfig(siteConfig, configPath) + common.CheckErr(writers.SetSiteConfig(siteConfig, configPath)) } else { fmt.Printf("Could not locate '%v' theme: %v\n", repoName, err) } diff --git a/cmd/theme_remove.go b/cmd/theme_remove.go index e4b851d2..b932d36e 100644 --- a/cmd/theme_remove.go +++ b/cmd/theme_remove.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os" + "plenti/common" "plenti/readers" "plenti/writers" @@ -44,7 +45,7 @@ theme folder within the "themes/" directory. // Remove the corresponding theme_config entry. delete(siteConfig.ThemeConfig, repoName) // Update the config file on the filesystem. - writers.SetSiteConfig(siteConfig, configPath) + common.CheckErr(writers.SetSiteConfig(siteConfig, configPath)) // Delete the corresponding theme folder. if err := os.RemoveAll("themes/" + repoName); err != nil { log.Fatalf("Could not delete theme folder: %v\n", err) diff --git a/cmd/type.go b/cmd/type.go index e0047f0c..5512002a 100644 --- a/cmd/type.go +++ b/cmd/type.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os" + "plenti/common" "strings" "github.com/spf13/cobra" @@ -51,11 +52,12 @@ Optionally add a _blueprint.json file to define the default field structure for Run: func(cmd *cobra.Command, args []string) { typeName := args[0] + // shoud we stop here on error from either? if SingleTypeFlag { - singleTypeProcess(typeName) - } else { - doTypeContentPath(typeName) + common.CheckErr(singleTypeProcess(typeName)) + } else { + common.CheckErr(doTypeContentPath(typeName)) } if EndpointFlag { @@ -75,35 +77,36 @@ Optionally add a _blueprint.json file to define the default field structure for }, } -func doTypeContentPath(typeName string) { +func doTypeContentPath(typeName string) error { typeContentPath := fmt.Sprintf("content/%s", strings.Trim(typeName, " /")) // !os.IsNotExist is true, the path exists. os.IsExist(err) == nil for Stat if file exists if _, err := os.Stat(typeContentPath); !os.IsNotExist(err) { fmt.Printf("A Type content source with the same name located at \"%s/\" already exists\n", typeContentPath) - return + // an error? + return nil } if _, err := os.Stat(typeContentPath + ".json"); !os.IsNotExist(err) { // error or not? fmt.Printf("A single file Type content source with the same name located at \"%s.json\" already exists\n", typeContentPath) - return + return nil } fmt.Printf("Creating new Type content source: %s/\n", typeContentPath) if err := os.MkdirAll(typeContentPath, os.ModePerm); err != nil { - log.Fatalf("Can't create type named \"%s\": %s", typeName, err) + return fmt.Errorf("Can't create type named \"%s\": %w", typeName, err) } if _, err := os.OpenFile(typeContentPath+"/_blueprint.json", os.O_RDONLY|os.O_CREATE, os.ModePerm); err != nil { - log.Fatalf("Can't create _blueprint.json for type \"%s\": %s", typeName, err) + return fmt.Errorf("Can't create _blueprint.json for type \"%s\": %w", typeName, err) } - + return nil } func singleTypeProcess(typeName string) error { - singleTypePath := "content/" + typeName + ".json" - _, singleTypeExistsErr := os.Stat(singleTypePath) + singleTypePath := fmt.Sprintf("content/%s.json", typeName) + _, err := os.Stat(singleTypePath) - if singleTypeExistsErr == nil { + if err == nil { errorMsg := fmt.Sprintf("A single type content source with the same name located at \"%s\" already exists\n", singleTypePath) fmt.Printf(errorMsg) return errors.New(errorMsg) @@ -111,24 +114,22 @@ func singleTypeProcess(typeName string) error { fmt.Printf("Creating new single type content source: %s\n", singleTypePath) - f, createSingleTypeErr := os.OpenFile(singleTypePath, os.O_RDWR|os.O_CREATE, os.ModePerm) + f, err := os.OpenFile(singleTypePath, os.O_RDWR|os.O_CREATE, os.ModePerm) - if createSingleTypeErr != nil { - errorMsg := fmt.Sprintf("Can't create single type named \"%s\": %s", typeName, createSingleTypeErr) - fmt.Printf(errorMsg) - return errors.New(errorMsg) + if err != nil { + errorMsg := fmt.Errorf("Can't create single type named \"%s\": %w", typeName, err) + fmt.Println(errorMsg) + return errorMsg } - _, err := f.Write([]byte("{}")) + _, err = f.Write([]byte("{}")) if err != nil { - errorMsg := fmt.Sprintf("Can't add empty curly brackets to single type named \"%s\": %s", typeName, createSingleTypeErr) - fmt.Printf(errorMsg) - return errors.New(errorMsg) + err = fmt.Errorf("Can't add empty curly brackets to single type named \"%s\": %w", typeName, err) + fmt.Println(err) + return err } - - defer f.Close() - - return nil + // can be non-nil error + return f.Close() } func init() { diff --git a/cmd/watcher.go b/cmd/watcher.go new file mode 100644 index 00000000..dd21df77 --- /dev/null +++ b/cmd/watcher.go @@ -0,0 +1,134 @@ +package cmd + +import ( + "fmt" + "log" + "os" + "path/filepath" + "plenti/cmd/build" + "plenti/common" + "time" + + "github.com/fsnotify/fsnotify" +) + +type watcher struct { + *fsnotify.Watcher +} + +func gowatch(buildPath string) { + // Creates a new file watcher. + wtch, err := fsnotify.NewWatcher() + // stop here as nothing will be watched + if err != nil { + log.Fatalf("couldn't create 'fsnotify.Watcher'") + } + go func() { + + // this can error + defer wtch.Close() + w := &watcher{wtch} + w.watch(buildPath) + }() + +} + +// Watch looks for updates to filesystem to prompt a site rebuild. +func (w *watcher) watch(buildPath string) { + // die on any error or will loop infinitely + // Watch specific directories for changes (only if they exist). + if _, err := os.Stat("content"); !os.IsNotExist(err) { + if err := filepath.Walk("content", w.watchDir(buildPath)); err != nil { + log.Fatalf("Error watching 'content/' folder for changes: %v\n", err) + } + } + if _, err := os.Stat("layout"); !os.IsNotExist(err) { + if err := filepath.Walk("layout", w.watchDir(buildPath)); err != nil { + log.Fatalf("Error watching 'layout/' folder for changes: %v\n", err) + } + } + if _, err := os.Stat("assets"); !os.IsNotExist(err) { + if err := filepath.Walk("assets", w.watchDir(buildPath)); err != nil { + log.Fatalf("Error watching 'assets/' folder for changes: %v\n", err) + } + } + if err := w.Add("plenti.json"); err != nil { + log.Fatalf("couldn't add 'plenti.json' to wather") + + } + if err := w.Add("package.json"); err != nil { + log.Fatalf("couldn't add 'package.json' to watcher") + + } + + done := make(chan bool) + + // Set delay for batching events. + ticker := time.NewTicker(300 * time.Millisecond) + // Create array for storing double firing events (happens when saving files in some text editors). + events := make([]fsnotify.Event, 0) + + go func() { + for { + select { + // Watch for events. + case event := <-w.Events: + // Don't rebuild when build dir is added or deleted. + if event.Name != "./"+buildPath { + // Add current event to array for batching. + events = append(events, event) + } + case <-ticker.C: + // Checks on set interval if there are events. + if len(events) > 0 { + // Display messages for each events in batch. + for _, event := range events { + if event.Op&fsnotify.Create == fsnotify.Create { + build.Log("File create detected: " + event.String()) + common.CheckErr(w.Add(event.Name)) + build.Log("Now watching " + event.Name) + } + if event.Op&fsnotify.Write == fsnotify.Write { + build.Log("File write detected: " + event.String()) + } + if event.Op&fsnotify.Remove == fsnotify.Remove { + build.Log("File delete detected: " + event.String()) + } + if event.Op&fsnotify.Rename == fsnotify.Rename { + build.Log("File rename detected: " + event.String()) + } + } + // Rebuild only one time for all batched events. + Build() + // Empty the batch array. + events = make([]fsnotify.Event, 0) + + } + + // Watch for errors. + case err := <-w.Errors: + if err != nil { + fmt.Printf("\nFile watching error: %s\n", err) + } + } + } + }() + + <-done +} + +// Closure that enables passing buildPath as arg to callback. +func (w *watcher) watchDir(buildPath string) filepath.WalkFunc { + // Callback for walk func: searches for directories to add watchers to. + return func(path string, fi os.FileInfo, err error) error { + // Skip the "public" build dir to avoid infinite loops. + if fi.IsDir() && fi.Name() == buildPath { + return filepath.SkipDir + } + // Add watchers only to nested directory. + if fi.Mode().IsDir() { + return w.Add(path) + } + return nil + } +} diff --git a/common/errs.go b/common/errs.go new file mode 100644 index 00000000..5dbee689 --- /dev/null +++ b/common/errs.go @@ -0,0 +1,10 @@ +package common + +import "log" + +// CheckErr is a basic common means to handle errors, can add more logic later. +func CheckErr(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/generators/main.go b/generators/main.go index 8a5a5d46..d5b95c9d 100644 --- a/generators/main.go +++ b/generators/main.go @@ -1,9 +1,11 @@ package main import ( + "fmt" "io/ioutil" "os" "path/filepath" + "plenti/common" "strings" ) @@ -11,46 +13,80 @@ import ( func main() { // Reads all files in "defaults" folder and // encodes them as string literals in generated/defaults.go - generate("defaults") + common.CheckErr(generate("defaults")) // Reads all files in "defaults_bare" folder and // encodes them as string literals in generated/defaults_bare.go - generate("defaults_bare") + common.CheckErr(generate("defaults_bare")) // Reads all files in "defaults_node_modules" folder and // encodes them as string literals in generated/defaults_node_modules.go - generate("defaults_node_modules") + common.CheckErr(generate("defaults_node_modules")) // Reads all files in "ejected" folder and // encodes them as string literals in generated/ejected.go - generate("ejected") + common.CheckErr(generate("ejected")) } -func generate(name string) { - out, _ := os.Create("generated/" + name + ".go") - out.Write([]byte("package generated")) - out.Write([]byte("\n\n// Do not edit, this file is automatically generated.")) - out.Write([]byte("\n\n// " + strings.Title(name) + ": scaffolding used in 'build' command")) - out.Write([]byte("\nvar " + strings.Title(name) + " = map[string][]byte{\n")) - filepath.Walk(name, +func generate(name string) error { + fp := fmt.Sprintf("generated/%s.go", name) + out, err := os.Create(fp) + if err != nil { + return fmt.Errorf("couldn't create %s in 'generate': %w", fp, err) + } + if _, err = out.Write([]byte("package generated")); err != nil { + return fmt.Errorf("error in 'generate': %w", err) + } + if _, err = out.Write([]byte("\n\n// Do not edit, this file is automatically generated.")); err != nil { + return fmt.Errorf("error in 'generate': %w", err) + } + if _, err = out.Write([]byte( + fmt.Sprintf("\n\n// %s: scaffolding used in 'build' command", strings.Title(name)))); err != nil { + return fmt.Errorf("error in 'generate': %w", err) + } + if _, err = out.Write([]byte( + fmt.Sprintf( + "\nvar %s = map[string][]byte{\n", strings.Title(name), + ))); err != nil { + return fmt.Errorf("error in 'generate': %w", err) + } + + if err = filepath.Walk(name, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { // Get the contents of the current file. - content, _ := ioutil.ReadFile(path) + content, err := ioutil.ReadFile(path) + if err != nil { + return err + } // Correct filename of the .gitignore file. if strings.HasSuffix(path, "_plenti_replace") { path = strings.TrimSuffix(path, "_plenti_replace") } // Add a key for the filename to the map. - out.Write([]byte("\t\"" + strings.TrimPrefix(path, name) + "\": []byte(`")) + if _, err := out.Write([]byte( + fmt.Sprintf("\t\"%s\": []byte(`", strings.TrimPrefix(path, name))), + ); err != nil { + return err + } + // Escape the backticks that would break string literals escapedContent := strings.Replace(string(content), "`", "`+\"`\"+`", -1) // Add the content as the value of the map. - out.Write([]byte(escapedContent)) + if _, err := out.Write([]byte(escapedContent)); err != nil { + return err + } // End the specific file entry in the map. - out.Write([]byte("`),\n")) + if _, err = out.Write([]byte("`),\n")); err != nil { + return err + } } return nil - }) - out.Write([]byte("}\n")) + }); err != nil { + return fmt.Errorf("error walking in 'generate': %w", err) + } + if _, err := out.Write([]byte("}\n")); err != nil { + return fmt.Errorf("error in 'generate': %w", err) + } + return nil } diff --git a/go.mod b/go.mod index 9bdccc05..d0db91b7 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/manifoldco/promptui v0.7.0 github.com/mattn/go-colorable v0.1.7 // indirect - github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.3.3 // indirect github.com/pelletier/go-toml v1.8.0 // indirect github.com/smartystreets/assertions v1.1.1 // indirect @@ -21,8 +20,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.6.1 // indirect - golang.org/x/sys v0.0.0-20200803150936-fd5f0c170ac3 // indirect - golang.org/x/text v0.3.3 // indirect + golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect gopkg.in/ini.v1 v1.57.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect rogchap.com/v8go v0.2.0 diff --git a/go.sum b/go.sum index 14a4d808..a68e4d14 100644 --- a/go.sum +++ b/go.sum @@ -292,6 +292,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -327,6 +329,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -357,8 +361,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803150936-fd5f0c170ac3 h1:Q8sHd8ZmZZguDQWkUYcD4pIRG5dG+euDEmNyknTRbGs= -golang.org/x/sys v0.0.0-20200803150936-fd5f0c170ac3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/readers/site_config.go b/readers/site_config.go index fdf08ea1..32527634 100644 --- a/readers/site_config.go +++ b/readers/site_config.go @@ -2,8 +2,8 @@ package readers import ( "encoding/json" - "fmt" "io/ioutil" + "log" ) // SiteConfig is the site's configuration file values. @@ -35,7 +35,7 @@ func GetSiteConfig(basePath string) (SiteConfig, string) { configFile, _ := ioutil.ReadFile(configPath) err := json.Unmarshal(configFile, &siteConfig) if err != nil { - fmt.Printf("Unable to read site config file: %s\n", err) + log.Fatalf("Unable to read site config file: %v\n", err) } // If build directory is not set in config, use default diff --git a/writers/site_config.go b/writers/site_config.go index c9e7d20f..ea7ed245 100644 --- a/writers/site_config.go +++ b/writers/site_config.go @@ -9,16 +9,19 @@ import ( ) // SetSiteConfig writes values to the site's configuration file. -func SetSiteConfig(siteConfig readers.SiteConfig, configPath string) { +func SetSiteConfig(siteConfig readers.SiteConfig, configPath string) error { result, err := json.MarshalIndent(siteConfig, "", "\t") if err != nil { - fmt.Printf("Unable to marshal JSON: %s\n", err) + return fmt.Errorf("Unable to marshal JSON: %v", err) + } // Write values to site config file for the project. - writeErr := ioutil.WriteFile(configPath, result, os.ModePerm) - if writeErr != nil { - fmt.Printf("Unable to write to config file: %s\n", writeErr) + err = ioutil.WriteFile(configPath, result, os.ModePerm) + if err != nil { + return fmt.Errorf("Unable to write to config file: %w", err) + } + return nil }