git-fmt 0.2.1.2 → 0.2.2.0
raw patch · 8 files changed
+94/−255 lines, 8 filesdep ~aeson
Dependency ranges changed: aeson
Files
- CHANGELOG.md +0/−82
- README.md +0/−94
- git-fmt.cabal +6/−6
- src/Git/Fmt.hs +35/−30
- src/Git/Fmt/Exit.hs +39/−0
- src/Git/Fmt/Options/Applicative/Parser.hs +10/−1
- src/Git/Fmt/Process.hs +4/−3
- src/System/IO/Extra'.hs +0/−39
− CHANGELOG.md
@@ -1,82 +0,0 @@-## Changelog--#### Upcoming--#### v0.2.1.2--*Revisions*--* Fixed a bug causing prettifying to fail across filesystem boundaries. ([#72](https://github.com/hjwylde/git-fmt/issues/72))--#### v0.2.1.1--*Revisions*--* Fixed a bug where passing arguments would only work when running in the git directory. ([#57](https://github.com/hjwylde/git-fmt/issues/57))--#### v0.2.1.0--*Minor*--* Added default use of stdin and stdout when variables not specified in a program command. ([#49](https://github.com/hjwylde/git-fmt/issues/49))--#### v0.2.0.2--*Revisions*--* Fixed a bug causing prettifying to fail across filesystem boundaries. ([#72](https://github.com/hjwylde/git-fmt/issues/72))--#### v0.2.0.1--*Revisions*--* Fixed a bug where passing arguments would only work when running in the git directory. ([#57](https://github.com/hjwylde/git-fmt/issues/57))--#### v0.2.0.0--*Major*--* Removed `--list-ugly` and `--dry-run` options. ([#29](https://github.com/hjwylde/git-fmt/issues/29))-* Restricted use of `--quiet` and `--verbose` at the same time. ([#35](https://github.com/hjwylde/git-fmt/issues/35))-* Updated project structure to delegate pretty printing to other binaries. ([#38](https://github.com/hjwylde/git-fmt/issues/38))-* Added a `.omniyaml.yaml` config file. ([#38](https://github.com/hjwylde/git-fmt/issues/38))--*Minor*--* Added `--mode` option (either `normal` or `dry-run`). ([#29](https://github.com/hjwylde/git-fmt/issues/29))-* Added `--null` option (use the null terminator as the delimiter for inputs). ([#27](https://github.com/hjwylde/git-fmt/issues/27))-* Added support for directories as arguments (directories include all files within recursively). ([#30](https://github.com/hjwylde/git-fmt/issues/30))-* Added parallelisation. ([#48](https://github.com/hjwylde/git-fmt/issues/48))--*Revisions*--* Added a warning for when files aren't found. ([#29](https://github.com/hjwylde/git-fmt/issues/29))-* Updated internal use of `git ls-files` to use the null terminator option. ([#27](https://github.com/hjwylde/git-fmt/issues/27))-* Fixed debug log messages to have timestamp and log level on all lines. ([#33](https://github.com/hjwylde/git-fmt/issues/33))-* Tidied up error messages from git. ([#40](https://github.com/hjwylde/git-fmt/issues/40))-* Tidied up error messages from parsing the config. ([#43](https://github.com/hjwylde/git-fmt/issues/43))--#### v0.1.0.3--*Revisions*--* Fixed a bug where passing arguments would only work when running in the git directory. ([#57](https://github.com/hjwylde/git-fmt/issues/57))--#### v0.1.0.2--*Revisions*--* Fixed a bug where UTF-8 characters in strings weren't printed properly. ([#26](https://github.com/hjwylde/git-fmt/issues/26))--#### v0.1.0.1--*Revisions*--* Fixed a bug where integers were printed as rationals. ([#25](https://github.com/hjwylde/git-fmt/issues/25))--#### v0.1.0.0--This is first release of the `git-fmt` binary!-It provides a basic syntax for formatting files in a git repository.-Currently only JSON is supported.-
− README.md
@@ -1,94 +0,0 @@-# git-fmt--[](http://www.repostatus.org/#wip)-[](https://travis-ci.org/hjwylde/git-fmt)-[](https://github.com/hjwylde/git-fmt/releases/latest)--(Side note: the formatting component of this project will eventually be split out and named omnifmt.)--`git-fmt` adds a custom command to Git that automatically formats code by using external- pretty-printers.-The idea was taken from [gofmt](https://golang.org/cmd/gofmt/), just with a bit of expansion to more- languages.--Formatted code is:--* Easier to write: never worry about minor formatting concerns while hacking away.-* Easier to read: when all code looks the same you need not mentally convert others' formatting- style into something you can understand.-* Easier to maintain: mechanical changes to the source don't cause unrelated changes to the file's- formatting; diffs show only the real changes.-* Uncontroversial: never have a debate about spacing or brace position ever again.--(Bullet points taken from https://blog.golang.org/go-fmt-your-code.)--### Installing--Installing `git-fmt` is easiest done using either- [stack](https://github.com/commercialhaskell/stack) (recommended) or- [Cabal](https://github.com/haskell/cabal).-Alternatively you may download a pre-compiled binary of the- [latest release](https://github.com/hjwylde/git-fmt/releases/latest).--**Using stack:**--```bash-stack install git-fmt-export PATH=$PATH:~/.local/bin-```--**Using Cabal:**--```bash-cabal-install git-fmt-export PATH=$PATH:~/.cabal/bin-```--### Usage--`git-fmt` itself just provides a way to select files in the git repository and pipe them through a- pretty-printer.-It also provides a dry-run mode that will show you which files need prettifying.--#### Configuration--Configuration is done through an `.omnifmt.yaml` file in the repository's top-level directory.--To show how, here's an example `.omnifmt.yaml` with 4 programs:-```yaml-haskell:- extensions: ["hs", "lhs"]- command: "stylish-haskell {{input}} > {{output}}"--javascript:- extensions: ["js"]- command: "js-beautify -"--json:- extensions: ["json"]- command: "json_pp"--ruby:- extensions: ["rb"]- command: "ruby-beautify {{input}}"-```--That's all it takes!-Each command declares how to read the input file and how to write to the output file.-If the input variable is omitted, it is fed to the command through `stdin`.-Likewise if the output variable is omitted it is read from `stdout`.-The output file is used to compare whether the original input was pretty or ugly before writing- to the original.--Extensions is pretty self explanatory, but if you use the same extension more than once then- precedence goes to the first defined pretty-printer.--#### Examples--See the [examples/](https://github.com/hjwylde/git-fmt/tree/master/examples/) directory for some- common pretty-printers and their corresponding omnifmt config.-Just don't forget to actually call the config file `.omnifmt.yaml`!--**NB:** Be careful when using these examples, I have not tested the pretty-printers fully to check- that they will not destroy your code by accident.-
git-fmt.cabal view
@@ -1,5 +1,5 @@ name: git-fmt-version: 0.2.1.2+version: 0.2.2.0 author: Henry J. Wylde maintainer: public@hjwylde.com@@ -17,8 +17,6 @@ category: Development build-type: Simple -extra-source-files: CHANGELOG.md README.md- source-repository head type: git location: git@github.com:hjwylde/git-fmt@@ -26,6 +24,7 @@ executable git-fmt main-is: Main.hs hs-source-dirs: app/+ ghc-options: -threaded -with-rtsopts=-N default-language: Haskell2010 other-extensions:@@ -48,18 +47,19 @@ Git.Fmt.Options.Applicative.Parser other-modules: Git.Fmt.Config,+ Git.Fmt.Exit, Git.Fmt.Process, Git.Fmt.Version,- Paths_git_fmt,- System.IO.Extra'+ Paths_git_fmt default-language: Haskell2010 other-extensions: FlexibleContexts+ MultiParamTypeClasses OverloadedStrings TemplateHaskell build-depends:- aeson == 0.8.*,+ aeson >= 0.8 && < 0.10, base == 4.8.*, directory == 1.2.*, exceptions == 0.8.*,
src/Git/Fmt.hs view
@@ -10,8 +10,9 @@ Options and handler for the git-fmt command. -} -{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-} module Git.Fmt ( -- * Options@@ -21,38 +22,40 @@ handle, ) where -import Control.Monad.Catch (MonadMask)-import Control.Monad.Extra-import Control.Monad.IO.Class-import Control.Monad.Logger-import Control.Monad.Parallel (MonadParallel)-import qualified Control.Monad.Parallel as Parallel-import Control.Monad.Reader+import Control.Applicative+import Control.Concurrent+import Control.Monad.Catch (MonadMask)+import Control.Monad.Extra+import Control.Monad.IO.Class+import Control.Monad.Logger+import Control.Monad.Parallel (MonadParallel)+import qualified Control.Monad.Parallel as Parallel+import Control.Monad.Reader -import Data.List.Extra (chunksOf, linesBy, lower, nub)-import qualified Data.Text as T-import Data.Yaml (prettyPrintParseException)-import Data.Yaml.Include (decodeFileEither)+import Data.List.Extra (chunksOf, linesBy, lower, nub)+import Data.Maybe (fromMaybe)+import qualified Data.Text as T+import Data.Yaml (prettyPrintParseException)+import Data.Yaml.Include (decodeFileEither) -import Git.Fmt.Config as Config+import Git.Fmt.Config as Config+import Git.Fmt.Exit import Git.Fmt.Process-import GHC.IO.Exception (IOErrorType(..)) import Prelude hiding (read) import System.Directory.Extra hiding (withCurrentDirectory) import System.Exit import System.FilePath-import System.IO.Error-import System.IO.Extra' import System.IO.Temp -- | Options. data Options = Options {- optChatty :: Chatty,- optNull :: Bool,- optMode :: Mode,- argPaths :: [FilePath]+ optChatty :: Chatty,+ optNull :: Bool,+ optNumThreads :: Maybe Int,+ optMode :: Mode,+ argPaths :: [FilePath] } deriving (Eq, Show) @@ -73,6 +76,8 @@ (liftIO $ listFilesRecursive path) (return [path]) )+ numThreads <- liftIO getNumCapabilities >>= \numCapabilities ->+ return $ fromMaybe numCapabilities (optNumThreads options) unlessM (liftIO . doesFileExist $ gitDir </> Config.defaultFileName) $ panic (gitDir </> Config.defaultFileName ++ ": not found") @@ -83,7 +88,7 @@ let supportedFilePaths = filter (supported config . T.pack . drop 1 . lower . takeExtension) filePaths flip runReaderT config . withSystemTempDirectory "git-fmt" $ \tmpDir ->- Parallel.sequence_ . map sequence . nChunks 8 . flip map supportedFilePaths $ \filePath -> ifM (liftIO $ doesFileExist filePath)+ Parallel.sequence_ . map sequence . nChunks numThreads . flip map supportedFilePaths $ \filePath -> ifM (liftIO $ doesFileExist filePath) (fmt options filePath (tmpDir </> filePath)) ($(logWarn) $ T.pack (filePath ++ ": not found")) where@@ -120,11 +125,7 @@ normal filePath tmpFilePath = do $(logInfo) $ T.pack (filePath ++ ": prettified") - -- Try move the file, but if it's across a filesystem boundary then we may need to copy instead- liftIO $ renameFile tmpFilePath filePath `catchIOError` \e ->- if ioeGetErrorType e == UnsupportedOperation- then copyFile tmpFilePath filePath >> removeFile tmpFilePath- else ioError e+ liftIO $ renameFile tmpFilePath filePath dryRun :: (MonadIO m, MonadLogger m) => FilePath -> FilePath -> m () dryRun filePath _ = $(logInfo) $ T.pack (filePath ++ ": ugly")@@ -138,12 +139,12 @@ else panic ".git/: not found" runProgram :: (MonadIO m, MonadLogger m) => Program -> FilePath -> FilePath -> m (ExitCode, String, String)-runProgram program inputFilePath tmpFilePath = do+runProgram program filePath tmpFilePath = do liftIO $ createDirectoryIfMissing True (takeDirectory tmpFilePath) runCommand . T.unpack $ substitute (T.concat [command program, inputSuffix, outputSuffix]) [- (inputVariableName, T.pack $ '"':inputFilePath ++ "\""),- (outputVariableName, T.pack $ '"':tmpFilePath ++ "\"")+ (inputVariableName, quote filePath),+ (outputVariableName, quote tmpFilePath) ] where inputSuffix@@ -152,4 +153,8 @@ outputSuffix | usesOutputVariable (command program) = T.empty | otherwise = T.pack " > " `T.append` outputVariableName+ quote str = T.pack $ '"':concatMap escape str ++ "\""+ escape '\\' = "\\\\"+ escape '"' = "\\\""+ escape c = [c]
+ src/Git/Fmt/Exit.hs view
@@ -0,0 +1,39 @@++{-|+Module : Git.Fmt.Exit+Description : Extra exit utilities.++Copyright : (c) Henry J. Wylde, 2015+License : BSD3+Maintainer : public@hjwylde.com++Extra exit utilities.+-}++{-# LANGUAGE TemplateHaskell #-}++module Git.Fmt.Exit (+ -- * Exiting+ panicWith, panic, exitFast,+) where++import Control.Monad.IO.Class+import Control.Monad.Logger++import Data.Text (pack)++import System.Exit++-- | Panics, logging the error to stderr and exiting fast with the code.+panicWith :: (MonadIO m, MonadLogger m) => String -> Int -> m a+panicWith error code = $(logError) (pack error) >> exitFast code++-- | Panics, logging the error to stderr and exiting fast with 128.+panic :: (MonadIO m, MonadLogger m) => String -> m a+panic error = panicWith error 128++-- | Exits fast with the given code (may be 0 for success!).+exitFast :: (MonadIO m) => Int -> m a+exitFast 0 = liftIO exitSuccess+exitFast code = liftIO $ exitWith (ExitFailure code)+
src/Git/Fmt/Options/Applicative/Parser.hs view
@@ -15,6 +15,7 @@ gitFmtPrefs, gitFmtInfo, gitFmt, ) where +import Data.Char (isDigit) import Data.Version (showVersion) import Options.Applicative@@ -59,6 +60,11 @@ long "null", short '0', help "Input files are delimited by a null terminator instead of white space" ])+ <*> natOption (mconcat [+ long "threads", metavar "INT",+ value Nothing, showDefaultWith $ const "number of processors",+ help "Specify the number of threads to use"+ ]) <*> modeOption (mconcat [ long "mode", short 'm', metavar "MODE", value Normal, showDefaultWith $ const "normal",@@ -68,7 +74,10 @@ metavar "-- PATHS..." ]) where- modeOption = option $ readerAsk >>= \opt -> case opt of+ natOption = option $ readerAsk >>= \opt -> if all isDigit opt+ then return $ Just (read opt :: Int)+ else readerError $ "not a natural number `" ++ opt ++ "'"+ modeOption = option $ readerAsk >>= \opt -> case opt of "normal" -> return Normal "dry-run" -> return DryRun _ -> readerError $ "unrecognised mode `" ++ opt ++ "'"
src/Git/Fmt/Process.hs view
@@ -22,10 +22,11 @@ import Data.Text hiding (unwords) +import Git.Fmt.Exit+ import System.Exit-import System.IO.Extra'-import System.Process (CmdSpec (..), CreateProcess)-import qualified System.Process as System+import System.Process (CmdSpec (..), CreateProcess)+import qualified System.Process as System -- | Runs the given executable with the arguments. -- Returns the exit code, stdout and stderr.
− src/System/IO/Extra'.hs
@@ -1,39 +0,0 @@--{-|-Module : System.IO.Extra'-Description : Extra extra IO utilities.--Copyright : (c) Henry J. Wylde, 2015-License : BSD3-Maintainer : public@hjwylde.com--Extra extra IO utilities.--}--{-# LANGUAGE TemplateHaskell #-}--module System.IO.Extra' (- -- * Exiting- panicWith, panic, exitFast,-) where--import Control.Monad.IO.Class-import Control.Monad.Logger--import Data.Text (pack)--import System.Exit---- | Panics, logging the error to stderr and exiting fast with the code.-panicWith :: (MonadIO m, MonadLogger m) => String -> Int -> m a-panicWith error code = $(logError) (pack error) >> exitFast code---- | Panics, logging the error to stderr and exiting fast with 128.-panic :: (MonadIO m, MonadLogger m) => String -> m a-panic error = panicWith error 128---- | Exits fast with the given code (may be 0 for success!).-exitFast :: (MonadIO m) => Int -> m a-exitFast 0 = liftIO exitSuccess-exitFast code = liftIO $ exitWith (ExitFailure code)-