Hello community, here is the log from the commit of package shake for openSUSE:Factory checked in at 2016-06-07 23:48:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/shake (Old) and /work/SRC/openSUSE:Factory/.shake.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "shake" Changes: -------- --- /work/SRC/openSUSE:Factory/shake/shake.changes 2016-04-30 23:30:31.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.shake.new/shake.changes 2016-06-07 23:48:14.000000000 +0200 @@ -1,0 +2,12 @@ +Thu Jun 2 04:47:05 UTC 2016 - [email protected] + +- update to 0.15.8 +* Extra base bounds to rule out building on GHC 7.4 +* Require extra-1.4.8 +* better error message when calling need on a directory +* use displayException for inner exceptions +* Improve the documentation for priority/alternative +* optimise copyFileChanged +* change writeFile functions to MonadIO + +------------------------------------------------------------------- Old: ---- shake-0.15.6.tar.gz New: ---- shake-0.15.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ shake.spec ++++++ --- /var/tmp/diff_new_pack.sUSMWC/_old 2016-06-07 23:48:15.000000000 +0200 +++ /var/tmp/diff_new_pack.sUSMWC/_new 2016-06-07 23:48:15.000000000 +0200 @@ -19,7 +19,7 @@ %global pkg_name shake %bcond_with tests Name: shake -Version: 0.15.6 +Version: 0.15.8 Release: 0 Summary: Build system library, like Make, but more accurate dependencies Group: Development/Languages/Other ++++++ shake-0.15.6.tar.gz -> shake-0.15.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/CHANGES.txt new/shake-0.15.8/CHANGES.txt --- old/shake-0.15.6/CHANGES.txt 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/CHANGES.txt 2016-06-01 19:58:04.000000000 +0200 @@ -1,5 +1,15 @@ Changelog for Shake +0.15.8 + Extra base bounds to rule out building on GHC 7.4 +0.15.7 + Require extra-1.4.8 + #457, better error message when calling need on a directory + #456, use displayException for inner exceptions + Improve the documentation for priority/alternative + #448, fix FSATrace on Mac 10.11 + #444, optimise copyFileChanged + #58, change writeFile functions to MonadIO 0.15.6 Require the primitive package #431, make it an error to need a directory diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/docs/Manual.md new/shake-0.15.8/docs/Manual.md --- old/shake-0.15.6/docs/Manual.md 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/docs/Manual.md 2016-06-01 19:58:04.000000000 +0200 @@ -2,7 +2,7 @@ _See also: [Shake links](https://github.com/ndmitchell/shake#readme); [Why choose Shake](Why.md#readme); [Function documentation](https://hackage.haskell.org/packages/archive/shake/latest/doc/html/Development-Shake.html)_ -Shake is a Haskell library for writing build systems - designed as a replacement for `make`. This document describes how to get started with Shake, assuming no prior Haskell knowledge. First, let's take a look at a Shake build system: +Shake is a Haskell library for writing build systems -- designed as a replacement for `make`. This document describes how to get started with Shake, assuming no prior Haskell knowledge. First, let's take a look at a Shake build system: import Development.Shake import Development.Shake.Command @@ -114,7 +114,7 @@ * Using `need` to introduce a dependency on the `src` file, ensuring that if `src` changes then `out` will be rebuilt and that `src` will be up-to-date before any further commands are run. * Using `cmd` to run the command line `rot13 file.txt -o file.rot13`, which should read `file.txt` and write out `file.rot13` being the ROT13 encoding of the file. -Many rules follow this pattern - calculate some local variables, `need` some dependencies, then use `cmd` to perform some actions. We now discuss each of the three statements. +Many rules follow this pattern -- calculate some local variables, `need` some dependencies, then use `cmd` to perform some actions. We now discuss each of the three statements. #### Local variables @@ -178,13 +178,13 @@ Shake provides a complete library of filepath manipulation functions (see the [docs for `Development.Shake.FilePath`](https://hackage.haskell.org/package/shake/docs/Development-Shake-FilePath.html)), but the most common are: -* `str1 </> str2` - add the path components together with a slash, e.g. `"_build" </> "main.o"` equals `"_build/main.o"`. -* `str1 <.> str2` - add an extension, e.g. `"main" <.> "o"` equals `"main.o"`. -* `str1 ++ str2` - append two strings together, e.g. `"hello" ++ "world"` equals `"helloworld"`. -* `str1 -<.> str2` - replace an extension, e.g. `"main.c" -<.> "o"` equals `"main.o"`. -* `dropExtension str` - drop the final extension of a filepath if it has one, e.g. `dropExtension "main.o"` equals `"main"`, while `dropExtension "main"` equals `"main"`. -* `takeFileName str` - drop the path component, e.g. `takeFileName "_build/src/main.o"` equals `"main.o"`. -* `dropDirectory1 str` - drop the first path component, e.g. `dropDirectory1 "_build/src/main.o"` equals `"src/main.o"`. +* `str1 </> str2` -- add the path components together with a slash, e.g. `"_build" </> "main.o"` equals `"_build/main.o"`. +* `str1 <.> str2` -- add an extension, e.g. `"main" <.> "o"` equals `"main.o"`. +* `str1 ++ str2` -- append two strings together, e.g. `"hello" ++ "world"` equals `"helloworld"`. +* `str1 -<.> str2` -- replace an extension, e.g. `"main.c" -<.> "o"` equals `"main.o"`. +* `dropExtension str` -- drop the final extension of a filepath if it has one, e.g. `dropExtension "main.o"` equals `"main"`, while `dropExtension "main"` equals `"main"`. +* `takeFileName str` -- drop the path component, e.g. `takeFileName "_build/src/main.o"` equals `"main.o"`. +* `dropDirectory1 str` -- drop the first path component, e.g. `dropDirectory1 "_build/src/main.o"` equals `"src/main.o"`. ## Advanced Syntax diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/docs/Ninja.md new/shake-0.15.8/docs/Ninja.md --- old/shake-0.15.6/docs/Ninja.md 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/docs/Ninja.md 1970-01-01 01:00:00.000000000 +0100 @@ -1,45 +0,0 @@ -# Running Ninja builds with Shake - -_See also: [Shake links](https://github.com/ndmitchell/shake#readme); [Shake manual](Manual.md#readme)_ - -Shake supports the `.ninja` file format used by the [Ninja tool](https://ninja-build.org/). This document describes how to use Shake instead of Ninja, and why you might want to do so. - -#### Installing Shake - -1. Install the [Haskell Platform](https://www.haskell.org/platform/), which provides a Haskell compiler and standard libraries. -2. Type `cabal update`, to download information about the latest versions of all Haskell packages. -3. Type `cabal install shake --global`, to build and install Shake and all its dependencies. -4. Type `shake --help`, to verify that Shake was successfully installed. - -#### Running Shake - -Change to the directory you usually run Ninja from (where there is a `build.ninja` file) and instead of typing `ninja` type `shake`. Ninja defaults to guessing how many processors to use, while Shake defaults to only 1 processor, so you will probably want to run something like `shake -j` to use all processors or `-j4` to use 4 processors (with a number appropriate for your computer). - -The following Ninja options are available in Shake: - -* Print version is `--version` in Shake. -* Change directory before building is `--directory` in Shake. -* Specify the `.ninja` file is `--file` in Shake. -* Parallelism is `-j` in Shake. -* Avoiding starting new jobs if the load average is over a certain level is not currently supported in Shake. -* Keep going until a number of jobs fail is best approximated by `--keep-going` which keeps going regardless of how many jobs fail. -* Dry run is not supported in Shake. -* Show command lines while building is `--verbose` in Shake. -* Debugging stats is `--timings` in Shake. -* Debugging explanations are achieved with `--debug` (mostly for Shake developers) and `--report` for end users. -* Many of the Ninja subtools have equivalent versions inside `--report`. - -#### Additional features of Shake - -For people who are set up to run an existing `.ninja` build file, there are two features of Shake that may appeal: - -* If you build with `--report` the file `report.html` will be generated. Open that report file and you can see numerous details about the build - how good the parallel utilisation was, what changed to cause what to rebuild, summary statistics, a dependency graph and more. See the Help page in any generated report for more details. -* If you build with `--progress` the console titlebar will display a predicted completion time, how many seconds until your build completes. The predicted time will be fairly inaccurate the first time round, but future runs are influenced by recorded timings, and can produce useful guesses. -* If you build with `--lint` certain invariants will be checked, and an error will be raised if they are violated. For example, if you depend on a generated file via `depfile`, but do not list it as a dependency (even an order only dependency), an error will be raised. - -#### FAQ - -* If I get this working, or can't get it working because of a bug, do you care? Yes - please [raise an issue](https://github.com/ndmitchell/issues). -* Is Shake compatible with all Ninja features? Shake has support for everything in the Ninja manual - including response files, deps, pools and restat. Shake does not yet support rebuilding a file if the command line changes (if people rely on this feature, I am happy to add it). I am unaware of any Ninja files that don't work, but would be surprised if there were not some corner cases that Shake gets wrong (but tell me, and I'll fix it). -* Is Shake faster or slower than Ninja? I have one data point - compiling LLVM on Windows under mingw they both take the same time to compile initially, and Ninja takes 0.9s for a nothing to do build vs Shake at 0.8s. Shake is slower at parsing Ninja files, so if you have _huge_ `.ninja` files (e.g. Chromium) Shake will probably be slower. Shake does less work if you don't specify deps, which is probably why it is faster on LLVM (but you should specify deps - it makes both Shake and Ninja faster). As people report more results I am sure both Shake and Ninja will be optimised. -* Why did you make Shake interpret `.ninja` files? There are a few reasons: 1) It seemed like fun. 2) The Ninja team have made both [CMake](http://www.cmake.org/) and [gyp](https://code.google.com/p/gyp/) both generate `.ninja` files, so Shake can now build far more projects. 3) Shake and Ninja are both designed to be fast, benchmarking them has already improved the speed of Shake. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/docs/Why.md new/shake-0.15.8/docs/Why.md --- old/shake-0.15.6/docs/Why.md 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/docs/Why.md 1970-01-01 01:00:00.000000000 +0100 @@ -1,83 +0,0 @@ -# Why choose Shake? - -_See also: [Shake links](https://github.com/ndmitchell/shake#readme); [Shake manual](Manual.md#readme)_ - -Shake is a library for writing build systems. Most large projects have a custom-written build system, and developers working on the project are likely to run the build system many times a day, spending a noticeable amount of time [waiting for the build system](http://xkcd.com/303/). This document explains why you might pick Shake over alternative tools for writing build systems (e.g. make, Ant, Scons). Shake primarily benefits two groups of people: - -* **Developers running the build system** - Shake based build systems run quickly, require little manual intervention and report estimated completion time as they go. -* **Developers writing the build system** - Shake provides a powerful language for writing build systems, has excellent support for writing large robust build systems, can express many types of build rules and provides profiling information to help speed up builds. - -In the rest of this document we explain and justify the above claims. Shake combines [cutting edge research](http://ndmitchell.com/downloads/paper-shake_before_building-10_sep_2012.pdf) with a [robust industrial-quality implementation](https://hackage.haskell.org/package/shake/). Shake is in constant use at many large organisations, including [a large investment bank](http://sc.com/), where it was originally developed and has been in use since 2009. - -#### Expresses many types of build rule - -Build systems run user supplied commands in an order satisfying dependencies. Many of the advantages of Shake are due to being able to express more powerful dependencies than other build tools. These dependency features ensure you can express the build system you want directly, without having to shoehorn your ideas into whatever dependencies your build tool provides. In particular, Shake can express both more dependencies (so things rebuild when they should) and more fine-grained dependencies (so things don't rebuild because something nearby changed). - -* Shake build systems can discover additional dependencies after running previous rules, allowing the build system to generate files and then examine them to determine their dependencies, rather than predict the dependencies in advance. Such capabilities are essential when working with generated source files, but often allow build systems to be structured more logically. -* Most build systems only allow dependencies between files, but Shake provides user definable dependencies. By default Shake includes support for dependencies on files, the existence of files, environment variables, directory contents and several others, and adding more to your project is easy. In particular you can include dependencies on things like compiler versions or information stored on a remote machine. - -#### Build systems run quickly - -Developers are likely to spend a long time waiting for their build system, and consequently Shake is designed to be fast. - -* The Shake implementation itself is highly optimised, in common with many build tools. In particular, Shake is designed for especially fast execution when nothing has changed -- a common case when developing. -* Shake benefits from its powerful dependencies, which can be more accurate and fine-grained, thus ensuring it only builds what is really necessary. -* Shake has excellent support for parallelism, fully utilising multicore machines. Shake also supports resource constraints, allowing builds to run with a higher level of parallelism than would otherwise be possible. As an example, you can limit disk-intensive operations (e.g. linking) without restricting CPU-intensive operations (e.g. compiling). -* Shake avoids rebuilding results where the dependencies are rebuilt but do not change, which is particularly useful for generated source files. The impact can reduce certain common patterns from build times of hours to build times of seconds. - -#### Build systems run reliably - -A build system is responsible for producing the files that developers are working with, so it is crucial that developers trust the result so they can properly investigate issues without considering build system involvement. - -* The powerful dependency system ensures that all dependencies can be expressed, ensuring the build never leaves stale files. -* The Shake implementation itself has an extensive test suite, combining several examples projects and over 100 small unit tests (140 at the last count). In addition, a random build system generator allows extensive testing of key properties, including sufficient rebuilding and correctness in the presence of errors. -* Shake builds can be run in a special "lint" mode to check global invariants, detecting and reporting problems such as dependency violations before they cause problems. - -#### Requires little manual intervention - -Most build systems occasionally require manual intervention, typically wiping the existing build and starting again, when the build system developers change something fundamental. Shake eliminates the need for any manual intervention, reducing time wasted by users of the build system. - -* The powerful dependencies ensure things that would normally require manual intervention can be tracked. For example, if the C compiler version is tracked as a dependency, then upgrading the C compiler will automatically rebuild all C files. -* Shake includes a version with each script, which can be changed to automatically force a complete rebuild. - -#### Reports estimated completion time - -Shake can report estimated completion time, allowing developers to plan their time better. - -* Shake provides both predicted completion time (in minutes and seconds) and the percentage completed. All predictions are based on previously recorded execution times for rules and dynamic predictions of machine load, providing reasonable estimates. -* Shake provides methods to display this information in the title bar on Windows, Linux and Mac, and on Windows 7/8 can also display this information as a progress bar in the taskbar. -* The progress information can be easily integrated into continuous integration systems, such as Team City. - -#### Powerful language - -Shake is implemented as a Haskell library, and Shake build systems are structured as Haskell programs which make heavy use of the Shake library functions. Shake is a delicate balance, providing access to the full power of Haskell (so build systems are not limited), yet also not requiring Haskell knowledge (suitable for any programmer). - -* By building on top of Haskell, Shake build systems benefit from a powerful standardised language. Having a full language available ensures that anything that would be unsuitable to express in a build system can be implemented in Haskell and used seamlessly. -* While Shake build systems are Haskell programs, they can be treated as a powerful version of make with slightly funny syntax. The build system requires no significant Haskell knowledge, and is designed so that most features are accessible by learning the "Shake syntax", without any appreciation of what the underlying Haskell means. - -#### Supports large robust systems - -Shake build systems can scale to tens of thousands of lines without becoming unwieldy. - -* Shake uses Haskell to provide facilities for properly structuring large projects. In particular, Shake build systems can use functions to reuse common functionality, modules to group functions into separate files and packages to allow reusing and sharing modules. -* The types and utility functions provided by Shake eliminate certain classes of common error, making it harder express invalid build systems. -* The lint mode performs sanity checks of the build system, allowing errors to be caught sooner. - -#### Provides profiling information - -Shake can generate profiling information allowing developers to both understand the current system, and identify opportunities for improvement. - -* The Shake profiling reports are standalone web pages containing plots, tables and graphs of useful information. -* The report can be used to speed up by the build by identifying which commands are most expensive, which files cause most rebuilding and any bottlenecks in parallelism. -* The report can examine details of the last run, providing information about what built and why. -* Profiles are always recorded, allowing profile reports to be generated after a run completes, without requesting any "profiling mode" in advance. Shake ensures profiling information is recorded with no measurable performance impact. -* Graphs can be generating showing dependencies, usually grouped by either file type or location, making it easy to see the overall structure of the build. -* Reports can be mined using a powerful querying language to determine custom information about your build. - -#### Why not? - -This document sets out the reasons you _should_ use Shake, but naturally there are some disadvantages: - -* Shake build systems are written in Haskell. While that provides many benefits, it does mean the Shake syntax follows that of Haskell, and some Shake errors are reported by the compiler as Haskell type errors. Despite being written in Haskell, the [user manual](Manual.md#readme) introduces Shake assuming no Haskell knowledge, so Haskell knowledge is not a requirement and hopefully should not be a barrier to using Shake. -* Shake is not likely to be installed by default, while Make almost always is. -* Shake does not provide default build rules, requiring everything to be expressed in your build system. In practice it seems that the default rules included with make are unsuitable for most large scale projects, but smaller projects may find themselves writing a few additional rules. It is hoped that additional experience with Shake will lead to a library of build rules being developed. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/shake.cabal new/shake-0.15.8/shake.cabal --- old/shake-0.15.6/shake.cabal 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/shake.cabal 2016-06-01 19:58:04.000000000 +0200 @@ -1,7 +1,7 @@ cabal-version: >= 1.10 build-type: Simple name: shake -version: 0.15.6 +version: 0.15.8 license: BSD3 license-file: LICENSE category: Development, Shake @@ -55,8 +55,6 @@ src/Test/Tup/newmath/square.h src/Paths.hs docs/Manual.md - docs/Ninja.md - docs/Why.md docs/shake-progress.png data-files: @@ -83,7 +81,7 @@ default-language: Haskell2010 hs-source-dirs: src build-depends: - base == 4.*, + base >= 4.5, directory, hashable >= 1.1.2.3, binary, @@ -97,7 +95,7 @@ js-jquery, js-flot, transformers >= 0.2, - extra >= 1.4.3, + extra >= 1.4.8, deepseq >= 1.1 if flag(portable) @@ -189,7 +187,7 @@ js-jquery, js-flot, transformers >= 0.2, - extra >= 1.4.3, + extra >= 1.4.8, deepseq >= 1.1, primitive @@ -263,13 +261,17 @@ test-suite shake-test default-language: Haskell2010 type: exitcode-stdio-1.0 - ghc-options: -main-is Test.main -with-rtsopts=-K1K main-is: Test.hs hs-source-dirs: src - ghc-options: -rtsopts - -- GHC bug 7646 means -threaded causes errors + + ghc-options: -main-is Test.main -rtsopts + if impl(ghc >= 7.6) + -- space leak introduced by -O1 in 7.4, see #445 + ghc-options: -with-rtsopts=-K1K if impl(ghc >= 7.8) + -- GHC bug 7646 (fixed in 7.8) means -threaded causes errors ghc-options: -threaded + build-depends: base == 4.*, directory, @@ -286,7 +288,7 @@ js-flot, transformers >= 0.2, deepseq >= 1.1, - extra >= 1.4.3, + extra >= 1.4.8, QuickCheck >= 2.0 if flag(portable) @@ -378,6 +380,7 @@ Test.Live Test.Makefile Test.Manual + Test.Match Test.Monad Test.Ninja Test.Oracle diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/Command.hs new/shake-0.15.8/src/Development/Shake/Command.hs --- old/shake-0.15.6/src/Development/Shake/Command.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/Command.hs 2016-06-01 19:58:03.000000000 +0200 @@ -44,7 +44,7 @@ import Development.Shake.FilePattern import Development.Shake.Types import Development.Shake.Rules.File -import Development.Shake.Derived(writeFile', withTempDir) +import Development.Shake.Derived --------------------------------------------------------------------- -- ACTUAL EXECUTION @@ -144,9 +144,36 @@ , not $ any ($ x) ignore] fsaCmd act opts file + | isMac = fsaCmdMac act opts file | useShell = runShell (unwords $ exe : args) $ \exe args -> act "fsatrace" $ opts : file : "--" : exe : args | otherwise = act "fsatrace" $ opts : file : "--" : exe : args + fsaCmdMac act opts file = do + let fakeExe e = liftIO $ do + me <- findExecutable e + case me of + Just re -> do + let isSystem = any (`isPrefixOf` re) [ "/bin" + , "/usr" + , "/sbin" + ] + if isSystem + then do + tmpdir <- getTemporaryDirectory + let fake = tmpdir ++ "fsatrace-fakes" ++ re + unlessM (doesFileExist fake) $ do + createDirectoryIfMissing True $ takeDirectory fake + copyFile re fake + return fake + else return re + Nothing -> return e + fexe <- fakeExe exe + if useShell + then do + fsh <- fakeExe "/bin/sh" + act "fsatrace" $ opts : file : "--" : fsh : "-c" : [unwords $ fexe : args] + else act "fsatrace" $ opts : file : "--" : fexe : args + fsatrace act = withTempFile $ \file -> do res <- fsaCmd act "rwm" file xs <- liftIO $ parseFSAT <$> readFileUTF8' file @@ -560,12 +587,6 @@ --------------------------------------------------------------------- -- UTILITIES --- Copied from Derived. Once Derived no longer exports cmd stuff, import from there. -withTempFile :: (FilePath -> Action a) -> Action a -withTempFile act = do - (file, del) <- liftIO newTempFile - act file `actionFinally` del - -- A better version of showCommandForUser, which doesn't escape so much on Windows showCommandForUser2 :: FilePath -> [String] -> String showCommandForUser2 cmd args = unwords $ map (\x -> if safe x then x else showCommandForUser x []) $ cmd : args diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/Core.hs new/shake-0.15.8/src/Development/Shake/Core.hs --- old/shake-0.15.6/src/Development/Shake/Core.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/Core.hs 2016-06-01 19:58:03.000000000 +0200 @@ -209,6 +209,13 @@ -- @ -- -- In this example @hello.txt@ will match the second rule, instead of raising an error about ambiguity. +-- +-- The 'priority' function obeys the invariants: +-- +-- @ +-- 'priority' p1 ('priority' p2 r1) === 'priority' p1 r1 +-- 'priority' p1 (r1 >> r2) === 'priority' p1 r1 >> 'priority' p1 r2 +-- @ priority :: Double -> Rules () -> Rules () priority i = modifyRules $ \s -> s{rules = Map.map (\(a,b,cs) -> (a,b,map (first $ const i) cs)) $ rules s} @@ -223,6 +230,8 @@ -- @ -- -- In this example @hello.txt@ will match the first rule, instead of raising an error about ambiguity. +-- Inside 'alternatives' the 'priority' of each rule is not used to determine which rule matches, +-- but the resulting match uses that priority compared to the rules outside the 'alternatives' block. alternatives :: Rules () -> Rules () alternatives = modifyRules $ \r -> r{rules = Map.map f $ rules r} where diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/Derived.hs new/shake-0.15.8/src/Development/Shake/Derived.hs --- old/shake-0.15.6/src/Development/Shake/Derived.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/Derived.hs 2016-06-01 19:58:03.000000000 +0200 @@ -124,11 +124,9 @@ copyFileChanged :: FilePath -> FilePath -> Action () copyFileChanged old new = do need [old] - eq <- liftIO $ doesFileExist new &&^ do - withBinaryFile old ReadMode $ \h1 -> withBinaryFile new ReadMode $ \h2 -> - liftM2 (==) (hFileSize h1) (hFileSize h2) &&^ - liftM2 (==) (BS.hGetContents h1) (BS.hGetContents h2) - unless eq $ do + -- in newer versions of the directory package we can use copyFileWithMetadata which (we think) updates + -- the timestamp as well and thus no need to read the source file twice. + unlessM (liftIO $ doesFileExist new &&^ fileEq old new) $ do putLoud $ "Copying from " ++ old ++ " to " ++ new -- copyFile does a lot of clever stuff with permissions etc, so make sure we just reuse it liftIO $ copyFile old new @@ -139,7 +137,7 @@ readFile' x = need [x] >> liftIO (readFile x) -- | Write a file, lifted to the 'Action' monad. -writeFile' :: FilePath -> String -> Action () +writeFile' :: MonadIO m => FilePath -> String -> m () writeFile' name x = liftIO $ writeFile name x @@ -149,12 +147,12 @@ readFileLines = fmap lines . readFile' -- | A version of 'writeFile'' which writes out a list of lines. -writeFileLines :: FilePath -> [String] -> Action () +writeFileLines :: MonadIO m => FilePath -> [String] -> m () writeFileLines name = writeFile' name . unlines -- | Write a file, but only if the contents would change. -writeFileChanged :: FilePath -> String -> Action () +writeFileChanged :: MonadIO m => FilePath -> String -> m () writeFileChanged name x = liftIO $ do b <- doesFileExist name if not b then writeFile name x else do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/Errors.hs new/shake-0.15.8/src/Development/Shake/Errors.hs --- old/shake-0.15.6/src/Development/Shake/Errors.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/Errors.hs 2016-06-01 19:58:03.000000000 +0200 @@ -1,4 +1,4 @@ -{-# LANGUAGE DeriveDataTypeable, PatternGuards, RecordWildCards #-} +{-# LANGUAGE DeriveDataTypeable, PatternGuards, RecordWildCards, CPP #-} -- | Errors seen by the user module Development.Shake.Errors( @@ -6,6 +6,7 @@ errorStructured, err, errorNoRuleToBuildType, errorRuleTypeMismatch, errorIncompatibleRules, errorMultipleRulesMatch, errorRuleRecursion, errorComplexRecursion, errorNoApply, + errorDirectoryNotFile ) where import Data.Tuple.Extra @@ -51,6 +52,12 @@ g [] = [] +errorDirectoryNotFile :: FilePath -> IO a +errorDirectoryNotFile dir = errorStructured + "Build system error - expected a file, got a directory" + [("Directory", Just dir)] + "Probably due to calling 'need' on a directory. Shake only permits 'need' on files." + errorNoRuleToBuildType :: TypeRep -> Maybe String -> Maybe TypeRep -> IO a errorNoRuleToBuildType tk k tv = structured (specialIsOracleKey tk) "Build system error - no _rule_ matches the _key_ type" @@ -141,4 +148,4 @@ show ShakeException{..} = unlines $ "Error when running Shake build system:" : map ("* " ++) shakeExceptionStack ++ - [show shakeExceptionInner] + [displayException shakeExceptionInner] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/FileInfo.hs new/shake-0.15.8/src/Development/Shake/FileInfo.hs --- old/shake-0.15.6/src/Development/Shake/FileInfo.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/FileInfo.hs 2016-06-01 19:58:03.000000000 +0200 @@ -8,6 +8,7 @@ import Control.Exception.Extra import Development.Shake.Classes +import Development.Shake.Errors import General.String import qualified Data.ByteString.Lazy as LBS import Data.Char @@ -108,7 +109,7 @@ let peek = do code <- peekFileAttributes fad if testBit code 4 then - errorIO $ "getFileInfo, expected a file, got a directory: " ++ unpackU x + errorDirectoryNotFile $ unpackU x else join $ liftM2 result (peekLastWriteTimeLow fad) (peekFileSizeLow fad) if res then @@ -152,7 +153,7 @@ getFileInfo x = handleBool isDoesNotExistError (const $ return Nothing) $ do s <- getFileStatus $ unpackU_ x if isDirectory s then - errorIO $ "getFileInfo, expected a file, got a directory: " ++ unpackU x + errorDirectoryNotFile $ unpackU x else result (extractFileTime s) (fromIntegral $ fileSize s) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Development/Shake/Monad.hs new/shake-0.15.8/src/Development/Shake/Monad.hs --- old/shake-0.15.6/src/Development/Shake/Monad.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Development/Shake/Monad.hs 2016-06-01 19:58:03.000000000 +0200 @@ -32,7 +32,7 @@ -- See https://ghc.haskell.org/trac/ghc/ticket/11555 catchSafe :: IO a -> (SomeException -> IO a) -> IO a -catchSafe a b = join (evaluate a) `catch_` b +catchSafe = catch_ -- | Run and then call a continuation. runRAW :: ro -> rw -> RAW ro rw a -> Capture (Either SomeException a) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test/Docs.hs new/shake-0.15.8/src/Test/Docs.hs --- old/shake-0.15.6/src/Test/Docs.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Test/Docs.hs 2016-06-01 19:58:03.000000000 +0200 @@ -87,6 +87,9 @@ ,"(==>) = undefined" ,"(<==) = ()" ,"infix 1 ==>" + ,"infix 0 ===" + ,"(===) :: a -> a -> b" + ,"(===) = undefined" ,"forAll f = f undefined" ,"remaining = 1.1" ,"done = 1.1" @@ -104,6 +107,8 @@ ,"myVariable = ()" ,"instance Eq (OptDescr a)" ,"(foo,bar,baz) = undefined" + ,"(p1,p2) = (0.0, 0.0)" + ,"(r1,r2) = (return () :: Rules(), return () :: Rules())" ,"xs = []" ,"ys = []" ,"out = \"\"" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test/Errors.hs new/shake-0.15.8/src/Test/Errors.hs --- old/shake-0.15.6/src/Test/Errors.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Test/Errors.hs 2016-06-01 19:58:03.000000000 +0200 @@ -60,9 +60,6 @@ obj "overlap.txt" %> \out -> writeFile' out "overlap.txt" obj "overlap.t*" %> \out -> writeFile' out "overlap.t*" obj "overlap.*" %> \out -> writeFile' out "overlap.*" - alternatives $ do - obj "alternative.t*" %> \out -> writeFile' out "alternative.txt" - obj "alternative.*" %> \out -> writeFile' out "alternative.*" obj "chain.2" %> \out -> do src <- readFile' $ obj "chain.1" @@ -153,9 +150,6 @@ build ["overlap.txt"] assertContents (obj "overlap.txt") "overlap.txt" crash ["overlap.txx"] ["key matches multiple rules","overlap.txx"] - build ["alternative.foo","alternative.txt"] - assertContents (obj "alternative.foo") "alternative.*" - assertContents (obj "alternative.txt") "alternative.txt" crash ["tempfile"] ["tempfile-died"] src <- readFile $ obj "tempfile" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test/FilePattern.hs new/shake-0.15.8/src/Test/FilePattern.hs --- old/shake-0.15.6/src/Test/FilePattern.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Test/FilePattern.hs 2016-06-01 19:58:03.000000000 +0200 @@ -183,6 +183,9 @@ (True, WalkTo _) <- return $ walk [""] Success{} <- quickCheckWithResult stdArgs{maxSuccess=1000} $ \(Pattern p) (Path x) -> + let label _ = property in + -- Ignore label to workaround QuickCheck space-leak + -- See #450 and https://github.com/nick8325/quickcheck/pull/93 let b = p ?== x in (if b then property else label "No match") $ unsafePerformIO $ do f b p x; return True return () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test/Match.hs new/shake-0.15.8/src/Test/Match.hs --- old/shake-0.15.6/src/Test/Match.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/shake-0.15.8/src/Test/Match.hs 2016-06-01 19:58:03.000000000 +0200 @@ -0,0 +1,63 @@ + +-- | Test the rule matching facilities - alternatives, priority etc. +module Test.Match(main) where + +import Development.Shake +import Test.Type + + +main = shakenCwd test $ \args obj -> do + want $ map obj args + let output x = \file -> writeFile' file x + + ["or*","*or"] |%> output "" + + alternatives $ do + obj "alternative.t*" %> output "alternative.t*" + obj "alternative.*" %> output "alternative.*" + + priority 100 $ priority 0 $ obj "priority.txt" %> output "100" + priority 50 $ obj "priority.txt" %> output "50" + + alternatives $ do + priority 20 $ obj "altpri.txt" %> output "20" + priority 40 $ obj "altpri.txt" %> output "40" + priority 30 $ obj "altpri.txt" %> output "30" + + alternatives $ do + priority 21 $ obj "altpri2.txt" %> output "21" + priority 22 $ obj "altpri2.txt" %> output "22" + priority 23 $ obj "altpri2.txt" %> output "23" + + priority 55 $ alternatives $ obj "x" %> output "55" + priority 51 $ obj "x" %> output "51" + + priority 42 $ alternatives $ obj "xx" %> output "42" + priority 43 $ obj "xx" %> output "43" + + priority 10 $ do + priority 7 $ obj "change" %> output "7" + priority 8 $ obj "change" %> output "8" + priority 9 $ obj "change" %> output "9" + + +test build obj = do + build ["clean"] + build ["or"] + + build ["alternative.foo","alternative.txt"] + assertContents (obj "alternative.foo") "alternative.*" + assertContents (obj "alternative.txt") "alternative.t*" + + build ["priority.txt"] + assertContents (obj "priority.txt") "100" + + build ["altpri.txt","altpri2.txt"] + assertContents (obj "altpri.txt") "20" + assertContents (obj "altpri2.txt") "23" + + build ["x","xx"] + assertContents (obj "x") "55" + assertContents (obj "xx") "43" + + assertException ["matches multiple rules"] $ build ["change","--quiet"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test/Type.hs new/shake-0.15.8/src/Test/Type.hs --- old/shake-0.15.6/src/Test/Type.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Test/Type.hs 2016-06-01 19:58:03.000000000 +0200 @@ -186,7 +186,9 @@ sleepFileTimeCalibrate = do let file = "output/calibrate" createDirectoryIfMissing True $ takeDirectory file - mtimes <- forM [1..10] $ \i -> fmap fst $ duration $ do + -- with 10 measurements can get a bit slow, see #451 + -- if it rounds to a second then 1st will be a fraction, but 2nd will be full second + mtimes <- forM [1..2] $ \i -> fmap fst $ duration $ do writeFile file $ show i let time = fmap (fst . fromMaybe (error "File missing during sleepFileTimeCalibrate")) $ getFileInfo $ packU file t1 <- time diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shake-0.15.6/src/Test.hs new/shake-0.15.8/src/Test.hs --- old/shake-0.15.6/src/Test.hs 2016-04-19 20:53:06.000000000 +0200 +++ new/shake-0.15.8/src/Test.hs 2016-06-01 19:58:03.000000000 +0200 @@ -35,6 +35,7 @@ import qualified Test.Live as Live import qualified Test.Makefile as Makefile import qualified Test.Manual as Manual +import qualified Test.Match as Match import qualified Test.Monad as Monad import qualified Test.Ninja as Ninja import qualified Test.Oracle as Oracle @@ -63,7 +64,7 @@ ,"config" * Config.main, "digest" * Digest.main, "directory" * Directory.main ,"docs" * Docs.main, "errors" * Errors.main, "orderonly" * OrderOnly.main ,"filepath" * FilePath.main, "filepattern" * FilePattern.main, "files" * Files.main, "filelock" * FileLock.main - ,"forward" * Forward.main + ,"forward" * Forward.main, "match" * Match.main ,"journal" * Journal.main, "lint" * Lint.main, "live" * Live.main, "makefile" * Makefile.main, "manual" * Manual.main ,"monad" * Monad.main, "parallel" * Parallel.main, "pool" * Pool.main, "random" * Random.main, "ninja" * Ninja.main ,"resources" * Resources.main, "assume" * Assume.main, "benchmark" * Benchmark.main
