headroom 0.1.1.0 → 0.1.2.0
raw patch · 31 files changed
+210/−41 lines, 31 filesdep ~file-embedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: file-embed
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- README.md +3/−8
- app/Main.hs +7/−4
- headroom.cabal +21/−2
- src/Headroom/AppConfig.hs +3/−3
- src/Headroom/Command/Gen.hs +1/−1
- src/Headroom/Command/Run.hs +7/−8
- src/Headroom/Command/Run/Env.hs +5/−5
- src/Headroom/FileSystem.hs +3/−3
- src/Headroom/License.hs +1/−1
- src/Headroom/Template/Mustache.hs +3/−3
- src/Headroom/Types.hs +3/−3
- test-data/code-samples/css/sample1.css +19/−0
- test-data/code-samples/css/sample2.css +6/−0
- test-data/code-samples/css/sample3.css +4/−0
- test-data/code-samples/haskell/full.hs +20/−0
- test-data/code-samples/haskell/replaced-simple.hs +6/−0
- test-data/code-samples/haskell/stripped.hs +5/−0
- test-data/code-samples/html/with-doctype.html +14/−0
- test-data/code-samples/html/without-doctype.html +14/−0
- test-data/code-samples/java/full.java +11/−0
- test-data/code-samples/js/sample1.js +19/−0
- test-data/code-samples/js/sample2.js +6/−0
- test-data/code-samples/js/sample3.js +3/−0
- test-data/code-samples/scala/full.scala +9/−0
- test-data/configs/full.yaml +12/−0
- test-data/test-template.mustache +1/−0
- test-data/test-traverse/a.html +0/−0
- test-data/test-traverse/foo/b.html +0/−0
- test-data/test-traverse/foo/bar/c.html +0/−0
- test-data/test-traverse/foo/test.xml +0/−0
CHANGELOG.md view
@@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## 0.1.2.0 (released 2020-03-06)+- FIXED: missing `test-data/` folder in dist tarball prevents tests execution+- bump _LTS Haskell_ to `15.2`+ ## 0.1.1.0 (released 2020-02-26) - FIXED: missing `embedded/` folder in dist tarball for _Hackage_ prevents successful build using _Cabal_ - bump _LTS Haskell_ to `15.1`
README.md view
@@ -1,11 +1,6 @@-<p align="center"><img src ="https://github.com/vaclavsvejcar/headroom/blob/master/doc/assets/logo.png?raw=true" width="200" /></p>--[](https://travis-ci.com/vaclavsvejcar/headroom)- So you are tired of managing license headers in your codebase by hand? Then __Headroom__ is the right tool for you! Now you can define your license header as [Mustache][web:mustache] template, put all the variables (such as author's name, year, etc.) into the [YAML][wiki:yaml] config file and Headroom will take care to add such license headers to all your source code files. __Table of Contents__-<!-- TOC --> - [1. Main Features](#1-main-features) - [2. Planned Features](#2-planned-features)@@ -23,7 +18,6 @@ - [5.2.1. Supported License Types](#521-supported-license-types) - [5.2.2. Supported File Types](#522-supported-file-types) -<!-- /TOC --> ## 1. Main Features - __License Header Management__ - allows to add, replace or drop license headers in source code files.@@ -31,8 +25,8 @@ - __Template Generator__ - generates license header templates for most popular _open source_ licenses. You can use these as-is, customize them or ignore them and use your custom templates. ## 2. Planned Features-- __init command__ - automates initial Headroom setup for your project (generates config files, detects source code file types and generates license template stubs for them)-- __binary distribution__ - pre-built binaries will be generated for each release for major OS platforms+- [[#24]][i24] __Init Command__ - automates initial Headroom setup for your project (generates config files, detects source code file types and generates license template stubs for them)+- __Binary Distribution__ - pre-built binaries will be generated for each release for major OS platforms ## 3. Installation > Binary distribution, pre-built packages and installation from Stackage will be available soon.@@ -244,6 +238,7 @@ | _Scala_ | `scala` | `.scala` | +[i24]: https://github.com/vaclavsvejcar/headroom/issues/24 [meta:new-issue]: https://github.com/vaclavsvejcar/headroom/issues/new [web:bsd-3]: https://opensource.org/licenses/BSD-3-Clause [web:cabal]: https://www.haskell.org/cabal/
app/Main.hs view
@@ -9,8 +9,10 @@ Functions responsible for application bootstrap. -}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-}+ module Main where import Headroom.Command ( Command(..)@@ -38,7 +40,7 @@ ) bootstrap :: Command -> IO ()-bootstrap command' = case command' of+bootstrap = \case Run sourcePaths templatePaths variables runMode debug -> commandRun (RunOptions runMode sourcePaths templatePaths variables debug) c@(Gen _ _) -> do@@ -46,6 +48,7 @@ commandGen (GenOptions genMode) parseGenMode :: MonadThrow m => Command -> m GenMode-parseGenMode (Gen True Nothing ) = return GenConfigFile-parseGenMode (Gen False (Just license)) = return $ GenLicense license-parseGenMode _ = throwM NoGenModeSelected+parseGenMode = \case+ Gen True Nothing -> pure GenConfigFile+ Gen False (Just license) -> pure $ GenLicense license+ _ -> throwM NoGenModeSelected
headroom.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: headroom-version: 0.1.1.0+version: 0.1.2.0 license: BSD3 license-file: LICENSE copyright: Copyright (c) 2019-2020 Vaclav Svejcar@@ -48,6 +48,25 @@ embedded/license/mit/java.mustache embedded/license/mit/js.mustache embedded/license/mit/scala.mustache+ test-data/test-template.mustache+ test-data/code-samples/css/sample1.css+ test-data/code-samples/css/sample2.css+ test-data/code-samples/css/sample3.css+ test-data/code-samples/haskell/full.hs+ test-data/code-samples/haskell/replaced-simple.hs+ test-data/code-samples/haskell/stripped.hs+ test-data/code-samples/html/with-doctype.html+ test-data/code-samples/html/without-doctype.html+ test-data/code-samples/java/full.java+ test-data/code-samples/js/sample1.js+ test-data/code-samples/js/sample2.js+ test-data/code-samples/js/sample3.js+ test-data/code-samples/scala/full.scala+ test-data/configs/full.yaml+ test-data/test-traverse/a.html+ test-data/test-traverse/foo/b.html+ test-data/test-traverse/foo/test.xml+ test-data/test-traverse/foo/bar/c.html source-repository head type: git@@ -93,7 +112,7 @@ aeson >=1.4.6.0 && <1.5, base >=4.7 && <5, either >=5.0.1.1 && <5.1,- file-embed >=0.0.11.1 && <0.1,+ file-embed >=0.0.11.2 && <0.1, lens >=4.18.1 && <4.19, mustache >=2.3.1 && <2.4, optparse-applicative >=0.15.1.0 && <0.16,
src/Headroom/AppConfig.hs view
@@ -73,7 +73,7 @@ -> m AppConfig -- ^ parsed configuration loadAppConfig path = do appConfig <- liftIO $ B.readFile path >>= parseAppConfig- return $ makePathsRelativeTo (takeDirectory path) appConfig+ pure $ makePathsRelativeTo (takeDirectory path) appConfig -- | Rewrites all file paths in 'AppConfig' to be relative to given file path. makePathsRelativeTo :: FilePath -- ^ file path to use@@ -101,7 +101,7 @@ parseVariables variables = fmap HM.fromList (mapM parse variables) where parse input = case T.split (== '=') input of- [key, value] -> return (key, value)+ [key, value] -> pure (key, value) _ -> throwM $ InvalidVariable input -- | Validates whether given 'AppConfig' contains valid data.@@ -109,7 +109,7 @@ => AppConfig -- ^ application config to validate -> m AppConfig -- ^ validated application config (or errors) validateAppConfig appConfig = case checked of- Success ac' -> return ac'+ Success ac' -> pure ac' Failure errors -> throwM $ InvalidAppConfig errors where checked = appConfig <$ checkSourcePaths <* checkTemplatePaths
src/Headroom/Command/Gen.hs view
@@ -27,7 +27,7 @@ env' :: GenOptions -> LogFunc -> IO Env-env' opts logFunc = return $ Env { envLogFunc = logFunc, envGenOptions = opts }+env' opts logFunc = pure $ Env { envLogFunc = logFunc, envGenOptions = opts } -- | Handler for /Generator/ command. commandGen :: GenOptions -- ^ /Generator/ command options
src/Headroom/Command/Run.hs view
@@ -62,8 +62,7 @@ env' opts logFunc = do let startupEnv = StartupEnv { envLogFunc = logFunc, envRunOptions = opts } merged <- runRIO startupEnv mergedAppConfig- let env = Env { envEnv = startupEnv, envAppConfig = merged }- return env+ pure $ Env { envEnv = startupEnv, envAppConfig = merged } -- | Handler for /Run/ command. commandRun :: RunOptions -- ^ /Run/ command options@@ -109,13 +108,13 @@ (\ex -> do logDebug $ displayShow (ex :: IOException) logWarn $ "Skipping missing configuration file: " <> fromString path- return Nothing+ pure Nothing ) mergeAppConfigs appConfigs = do let merged = mconcat appConfigs logDebug $ "Source AppConfig instances: " <> displayShow appConfigs logDebug $ "Merged AppConfig: " <> displayShow merged- return merged+ pure merged loadTemplates :: (HasAppConfig env, HasLogFunc env) => RIO env (M.Map FileType Text)@@ -131,7 +130,7 @@ fmap (t, ) (renderTemplate (acVariables appConfig) (p :: TemplateType)) ) parsed- return $ M.fromList rendered+ pure $ M.fromList rendered where extensions = templateExtensions (Proxy :: Proxy TemplateType) findPaths path = findFilesByExts path extensions@@ -142,7 +141,7 @@ let fileType = fileTypeByName . T.pack . takeBaseName $ path when (isNothing fileType) (logWarn $ "Skipping unrecognized template type: " <> fromString path)- return fileType+ pure fileType findSourceFiles :: HasAppConfig env => [FileType] -> RIO env [FilePath] findSourceFiles fileTypes = do@@ -160,7 +159,7 @@ withProgress = fmap (\(i, (h, p)) -> (progress i, h, p)) zipped progress curr = Progress curr (L.length paths) processed <- mapM (\(i, h, p) -> processHeader i h p) withProgress- return (L.length withProgress, L.length . filter (== True) $ processed)+ pure (L.length withProgress, L.length . filter (== True) $ processed) where withTemplate (fileType, path) = fmap (\t -> (Header fileType t, path)) (M.lookup fileType templates)@@ -183,7 +182,7 @@ msg' = if skipped then "Skipping file" else msg log' $ msg' <> ": " <> fromString path writeFileUtf8 path (action header fileContent)- return skipped+ pure skipped where log' msg = logInfo $ displayShow progress <> " " <> msg chooseAction runMode hasHeader = case runMode of
src/Headroom/Command/Run/Env.hs view
@@ -89,8 +89,8 @@ -> m AppConfig -- ^ application configuration toAppConfig opts = do variables' <- parseVariables (roVariables opts)- return $ mempty { acSourcePaths = roSourcePaths opts- , acTemplatePaths = roTemplatePaths opts- , acRunMode = roRunMode opts- , acVariables = variables'- }+ pure $ mempty { acSourcePaths = roSourcePaths opts+ , acTemplatePaths = roTemplatePaths opts+ , acRunMode = roRunMode opts+ , acVariables = variables'+ }
src/Headroom/FileSystem.hs view
@@ -61,7 +61,7 @@ -> m [FilePath] -- ^ list of found files listFiles fileOrDir = do isDir <- doesDirectoryExist fileOrDir- if isDir then listDirectory fileOrDir else return [fileOrDir]+ if isDir then listDirectory fileOrDir else pure [fileOrDir] where listDirectory dir = do names <- getDirectoryContents dir@@ -69,8 +69,8 @@ paths <- forM filteredNames $ \name -> do let path = dir </> name isDirectory <- doesDirectoryExist path- if isDirectory then listFiles path else return [path]- return $ concat paths+ if isDirectory then listFiles path else pure [path]+ pure $ concat paths -- | Loads file content in UTF8 encoding. loadFile :: MonadIO m
src/Headroom/License.hs view
@@ -59,6 +59,6 @@ | [rawLicenseType, rawFileType] <- TP.splitOn ":" raw = do licenseType <- parseLicenseType rawLicenseType fileType <- fileTypeByName rawFileType- return $ License licenseType fileType+ pure $ License licenseType fileType | otherwise = Nothing where parseLicenseType = readMaybe . T.unpack
src/Headroom/Template/Mustache.hs view
@@ -39,18 +39,18 @@ parseTemplate' :: MonadThrow m => Maybe Text -> Text -> m Mustache parseTemplate' name raw = case MU.compileTemplate templateName raw of Left err -> throwM $ ParseError (T.pack . show $ err)- Right res -> return $ Mustache res+ Right res -> pure $ Mustache res where templateName = T.unpack . fromMaybe "" $ name renderTemplate' :: MonadThrow m => HashMap Text Text -> Mustache -> m Text renderTemplate' variables (Mustache t@(MU.Template name _ _)) = case MU.checkedSubstitute t variables of- ([], rendered) -> return rendered+ ([], rendered) -> pure rendered (errs, rendered) -> let errs' = missingVariables errs in if length errs == length errs' then throwM $ MissingVariables (T.pack name) errs'- else return rendered+ else pure rendered where missingVariables = concatMap (\case
src/Headroom/Types.hs view
@@ -99,8 +99,8 @@ instance FromJSON RunMode where parseJSON (String s) = case T.toLower s of- "add" -> return Add- "drop" -> return Drop- "replace" -> return Replace+ "add" -> pure Add+ "drop" -> pure Drop+ "replace" -> pure Replace _ -> error $ "Unknown run mode: " <> T.unpack s parseJSON other = error $ "Invalid value for run mode: " <> show other
+ test-data/code-samples/css/sample1.css view
@@ -0,0 +1,19 @@+/*+ * Copyright AUTHOR+ * + * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ * + * http://www.apache.org/licenses/LICENSE-2.0+ * + * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++body {+ background: white;+}
+ test-data/code-samples/css/sample2.css view
@@ -0,0 +1,6 @@+++body {+ background: white;+ }+
+ test-data/code-samples/css/sample3.css view
@@ -0,0 +1,4 @@+body {+ background: white;+ }+
+ test-data/code-samples/haskell/full.hs view
@@ -0,0 +1,20 @@++{-|+Module : W+Description : Short description+Copyright : (c) Some Guy, 2013+ Someone Else, 2014+License : GPL-3+Maintainer : sample@email.com+Stability : experimental+Portability : POSIX++Here is a longer description of this module, containing some+commentary with @some markup@.+-}++{-# LANGUAGE OverloadedStrings #-}+module Test where++foo :: String+foo = "Hello, world!"
+ test-data/code-samples/haskell/replaced-simple.hs view
@@ -0,0 +1,6 @@+-- This is header+{-# LANGUAGE OverloadedStrings #-}+module Test where++foo :: String+foo = "Hello, world!"
+ test-data/code-samples/haskell/stripped.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE OverloadedStrings #-}+module Test where++foo :: String+foo = "Hello, world!"
+ test-data/code-samples/html/with-doctype.html view
@@ -0,0 +1,14 @@+<!--+ This is some comment.+ +-->+<!DOCTYPE html>+<html>+ <head>+ <meta charset="utf-8" />+ <title>Test title</title>+ </head>+ <body>+ Hello, World!+ </body>+</html>
+ test-data/code-samples/html/without-doctype.html view
@@ -0,0 +1,14 @@+<!--+ This is some comment.+ +-->++<html>+ <head>+ <meta charset="utf-8" />+ <title>Test title</title>+ </head>+ <body>+ Hello, World!+ </body>+</html>
+ test-data/code-samples/java/full.java view
@@ -0,0 +1,11 @@+/*+ * Some existing header here+ */++package foo;++class Hello {+ public static void main(String[] args) {+ System.out.println("Hello, world!");+ }+}
+ test-data/code-samples/js/sample1.js view
@@ -0,0 +1,19 @@+/*+ * Copyright AUTHOR+ * + * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ * + * http://www.apache.org/licenses/LICENSE-2.0+ * + * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++function answer() {+ return 42;+}
+ test-data/code-samples/js/sample2.js view
@@ -0,0 +1,6 @@+++function answer() {+ return 42;+}+
+ test-data/code-samples/js/sample3.js view
@@ -0,0 +1,3 @@+function answer() {+ return 42;+}
+ test-data/code-samples/scala/full.scala view
@@ -0,0 +1,9 @@+/*+ * Some existing header here+ */++package foo++object Hello extends App {+ println("Hello, world!")+}
+ test-data/configs/full.yaml view
@@ -0,0 +1,12 @@+run-mode: add++source-paths:+ - path/to/src++template-paths:+ - path/to/dir1+ - path/to/dir2++variables:+ copyright: (c) 2019 John Smith+ email: john.smith@example.com
+ test-data/test-template.mustache view
@@ -0,0 +1,1 @@+Hello, {{user}}
+ test-data/test-traverse/a.html view
+ test-data/test-traverse/foo/b.html view
+ test-data/test-traverse/foo/bar/c.html view
+ test-data/test-traverse/foo/test.xml view