Commit Graph

151 Commits

Author SHA1 Message Date
Dale Wijnand 722022ae97 Add conversions from Init/+Task to Taskable 2020-02-17 12:22:53 +00:00
Dale Wijnand fdfdd1ca47 Extract Taskable from ScopedTaskable 2020-02-17 12:22:53 +00:00
Eugene Yokota a8ab4ada68 Replace getResource("") trick
Fixes https://github.com/sbt/sbt/issues/5339

It seems like some tests are using `ClassLoader#getResource("")` to acquire the `classes` directory path. This does not seem to work on sbt 1.3.6, which returns `file:/home/travis/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.11.2/log4j-api-2.11.2.jar!/META-INF/versions/9/`. To workaround this issue, I've switched to loading the known folder name instead.
2019-12-27 16:43:20 -05:00
Eugene Yokota 1cfe14a877 Ignore the build ref case 2019-09-30 02:18:11 -04:00
Eugene Yokota d1993bcabb use hedgehog.Result 2019-09-30 02:09:02 -04:00
Eugene Yokota f2de61c681 check for ambiguous project names 2019-09-30 01:56:03 -04:00
Eugene Yokota 073c89059e make URI longer to avoid conflict 2019-09-30 01:56:00 -04:00
Eugene Yokota ad1596c400 increase example count 2019-09-30 01:53:50 -04:00
Charles O'Farrell 67a3eca698 Use hedgehog in ParseKey, Delegates, and ParserSpec test 2019-09-30 01:52:57 -04:00
Ethan Atkins fb15065438 Move implicit FileStamp JsonFormats into object
I realized it was probably not ideal to have these implicit JsonFormats
defined directly in the FileStamp object because they might
inadvertently be brought into scope with a wildcard import.
2019-08-09 12:18:22 -07:00
Ethan Atkins a3ac4c76a6 Bump scalafmt
Intellij had issues resolving 2.0.0-RCX so it will be nice to be using
the latest.
2019-07-18 12:40:21 -07:00
Eugene Yokota 41eca47e66 Fix Java version parsing
Fixes #4731
2019-05-29 23:11:20 -04:00
Ethan Atkins df51281d90 Remove dead test 2019-05-28 10:39:08 -07:00
Ethan Atkins 03bf539ce9 Add new ClassLoaderCache implementation
This commit adds a new ClassLoaderCache that builds on the
ClassLoaderCache that is present in zinc (and can be used to build an
instance of the zinc ClassLoaderCache to preserve compatibility). It
differs from the zinc classloader cache that it does not use direct
SoftReferences to classloaders. Instead, we create a wrapper loader
that can't load any classes and just delegates to its parent. This
allows us to add a thread that reaps the soft reference to the wrapper
loader. Crucially, we add a custom SoftReference class that has a strong
reference to the underlying classloader. This allows us to call close on
the strong reference.

The one issue with this approach is that we can't
rescue the jvm from crashing with an OOM: metaspace because the jvm
doesn't give us a chance to close and dereference the underlying
classloaders before it crashes. It WILL collect classloaders under
normal memory pressure, just not metaspace pressure. To fix this, I
check if the MaxMetaspaceSize is set via an MxBean and, if it is, we
fill the cache with regular soft references. We are going to change the
bash script to not set -XX:MaxMetaspaceSize by default so most builds
should probably end up correctly closing the classloaders after this
change. But we should break existing builds that set MaxMetaspaceSize
but don't crash.

As part of this commit, I audited all of the places where we were
instantiating ClassLoaderCache instances and instead pass in the
state's ClassLoaderCache instance. This reduces the total number of
classloaders created.
2019-05-28 09:53:35 -07:00
Ethan Atkins ec09e73437 Improve cache invalidation strategy
Previously the persistent attribute map was only reset when the file
event monitor detected a change. This made it possible for the cache to
be inconsistent with the state of the file system*. To fix this, I add an
observer on the file tree repository used by the continuous build that
invalidates the cache entry for any path for which it detects a change.
Invalidating the cache does not stamp the file. That only happens either
when a task asks for the stamp for that file or when the file event
monitor reports an event and we must check if the file was updated or
not.

After this change, touching a source file will not trigger a build
unless the contents of the file actually changes.

I added a test that touches one source file in a project and updates the
content of the other. If the source file that is only ever touched ever
triggers a build, then the test fails.

* This could lead to under-compilation because ExternalHooks would not
detect that the file had been updated.
2019-05-11 22:01:48 -07:00
Ethan Atkins b6ad077a72 Update io
The new io verion removes the PathFinder <-> Glob implicit translations.
It also has a number of small bug fixes related to directory listing via
FileTreeView.
2019-05-11 21:34:02 -07:00
Eugene Yokota b18f3e8710 Reduce the test noise by making id more realistic
Fixes #3893

This fixes the flaky ParserSpec by making the id generation more realistic ASCII identifiers.
2019-05-11 03:55:34 -04:00
Eugene Yokota 4b9533b124 ignore bad SDKMAN directories
Fixes #4655
2019-05-09 01:59:03 -04:00
Ethan Atkins 3319423369 Add full support for managing file task io
This commit unifies my previous work for automatically watching the
input files for a task with support for automatically tracking and
cleaning up the output files of a task. The big idea is that users may
want to define tasks that depend on the file outputs of other tasks and
we may not want to run the dependent tasks if the output files of the
parent tasks are unmodified.

For example, suppose we wanted to make a plugin for managing typescript
files. There may be, say, two tasks with the following inputs and
outputs:

compileTypescript = taskKey[Unit]("shells out to compile typescript files")
  fileInputs -- sourceDirectory / ** / "*.ts"
  fileOutputs -- target / "generated-js" / ** / "*.js"

minifyGeneratedJS = taskKey[Path]("minifies the js files generated by compileTypescript to a single combined js file.")
  dependsOn: compileTypeScript / fileOutputs

Given a clean build, the following should happen
> minifyGeneratedJS
// compileTypescript is run
// minifyGeneratedJS is run

> minifyGeneratedJS
// no op because nothing changed

> minifyGeneratedJS / clean
// removes the file returned by minifyGeneratedJS.previous

> minifyGeneratedJS
// re-runs minifyGeneratedJS with the previously compiled js artifacts

> compileTypescript / clean
// removes the generated js files

> minifyGeneratedJS
// compileTypescript is run because the previous clean removed the generated js files
// minifyGeneratedJS runs because the artifacts have changed

> clean
// removes the generated js files and the minified js file

> minifyGeneratedJS
// compileTypescript is run because the generated js files were
// minifyGeneratedJS is run both because it was removed and

Moreover, if compileTypescript fails, we want minifyGeneratedJS to fail
as well.

This commit makes this all possible. It adds a number of tasks to
sbt.nio.Keys that deal with the output files. When injecting settings, I
now identify all tasks that return Seq[File], File, Seq[Path] and Path
and create a hidden special task: dynamicFileOutputs: TaskKey[Seq[Path]]
This special task runs the underlying task and converts the result to
Seq[Path]. From there, we can have the tasks like changedOutputPaths
delegate to dynamicFileOutputs which, by proxy, runs the underlying
task. If any task in the input / output chain fails, the entire sequence
fails.

Unlike the fileInputs, we do not register the dynamicFileOutputs or
fileOutputs with continuous watch service so these paths will not
trigger a continuous build if they are modified. Only explicit unmanaged
input sources should should do that.

As part of this, I also added automatic generation of a custom clean task for
any task that returns Seq[File], File, Seq[Path] or Path. I also added
aggregation so that clean can be defined in a configuration or project
and it will automatically run clean for all of the tasks that have a
custom clean implementation in that task or project. The automatic clean
task will only delete files that are in the task target directory to
avoid accidentally deleting unmanaged files.
2019-05-02 14:36:08 -07:00
Ethan Atkins a5cefd45be Clean up nio apis
This commit refactors things so that the nio apis are located primarily
in the nio package. Because the nio keys are a first class sbt feature,
I had to add import sbt.nio._ and sbt.nio.Keys._ to the autoimports in
BuildUtil.scala
2019-05-02 14:36:06 -07:00
Ethan Atkins 72df8f674c Add support for managed task inputs
In my recent changes to watch, I have been moving towards a world in
which sbt manages the file inputs and outputs at the task level. The
main idea is that we want to enable a user to specify the inputs and
outputs of a task and have sbt able to track those inputs across
multiple task evaluations. Sbt should be able to automatically trigger a
build when the inputs change and it also should be able to avoid task
evaluation if non of the inputs have changed.

The former case of having sbt automatically watch the file inputs of a
task has been present since watch was refactored. In this commit, I
make it possible for the user to retrieve the lists of new, modified and
deleted files. The user can then avoid task evaluation if none of the
inputs have changed.

To implement this, I inject a number of new settings during project
load if the fileInputs setting is defined for a task. The injected
settings are:

allPathsAndAttributes -- this retrieves all of the paths described by
  the fileInputs for the task along with their attributes
fileStamps -- this retrieves all of the file stamps for the files
  returned by allPathsAndAttributes

Using these two injected tasks, I also inject a number of derived tasks,
such as allFiles, which returns all of the regular files returned by
allPathsAndAttributes and changedFiles, which returns all of the regular
files that have been modified since the last run.

Using these injected settings, the user is able to write tasks that
avoid evaluation if the inputs haven't changed.

foo / fileInputs += baseDirectory.value.toGlob / ** / "*.scala"
foo := {
  foo.previous match {
    case Some(p) if (foo / changedFiles).value.isEmpty => p
    case _ => fooImpl((foo / allFiles).value
  }
}

To make this whole mechanism work, I add a private task key:
val fileAttributeMap = taskKey[java.util.HashMap[Path, Stamp]]("...")
This keeps track of the stamps for all of the files that are managed by
sbt. The fileStamps task will first look for the stamp in the attribute
map and, only if it is not present, it will update the cache. This
allows us to ensure that a given file will only be stamped once per task
evaluation run no matter how the file inputs are specified. Moreover, in
a continuous build, I'm able to reuse the attribute map which can
significantly reduce latency because the default file stamping
implementation used by zinc is fairly expensive (it can take anywhere
between 300-1500ms to stamp 5000 8kb source files on my mac).

I also renamed some of the watch related keys to be a bit more clear.
2019-05-02 14:33:29 -07:00
Ethan Atkins 2deac62b00 Bump io
The newest version of io repackages a number of classes into the
sbt.nio.* packages. It also changes some of the semantics of glob
related apis. This commit updates all of the usages of the updated apis
within sbt but should have no functional difference.
2019-05-02 14:33:01 -07:00
Dale Wijnand 546476981c
Resolve compilation warnings in test/Delegates 2019-04-18 09:21:08 +01:00
Ethan Atkins 40d8d8876d Create Watch.scala
I decided that it makes sense to move all of the new watch code out of
the Watched companion object since the Watched trait itself is now
deprecated. I don't really like having the new code in Watched.scala
mixed with the legacy code, so I pulled it all out and moved it into the
Watch object. Since we have to put all of the logic for the Continuous
object in main in order to access the sbt.Keys object, it makes sense to
move the logic out of main-command and into command so that most of the
watch related logic is in the same subproject.
2019-03-30 16:39:10 -07:00
Eugene Yokota 29ebd1222c improve the implementation of expandJavaHomes 2019-03-26 23:06:49 -04:00
Eugene Yokota c0cd65af92 detection of SDKMAN managed JDKs 2019-03-26 18:37:36 -04:00
Eugene Yokota 6f19f76b40 migrate to ScalaTest FunSuite 2019-03-26 18:26:52 -04:00
Ethan Atkins ef08290ecc Add ClassLoaderCache
In order to speed up the start up time of the test and run tasks, I'm
introducing a ClassLoaderCache that can be used to avoid reloading the
classes in the project dependencies (which includes the scala library).
I made the api as minimal as possible so that we can iterate on the
implementation without breaking binary compatibility. This feature will
be gated on a feature flag, so I'm not concerned with the cache class
loaders being useable in every user configuration. Over time, I hope
that the CachedClassLoaders will be a drop in replacement for the
existing one-off class loaders*.

The LayeredClassLoader was adapted from the NativeCopyLoader. The main
difference is that the NativeCopyLoader extracts named shared libraries
into the task temp directory to ensure that the ephemeral libraries are
deleted after each task run. This is a problem if we are caching the
ClassLoader so for LayeredClassLoader I track the native libraries that
are extracted by the loader and I delete them either when the loader is
explicitly closed or in a shutdown hook.

* This of course means that we both must layer the class loaders
appropriately so that the project code is in a layer above the cached
loaders and we must correctly invalidate the cache when the project, or
its dependencies are updated.
2019-01-30 08:55:22 -08:00
Ethan Atkins ec22d6c0da Add LRUCache to sbt.internal
I am going to add a classloader cache to improve the startup performance
of the run and test tasks. To prevent the classloader cache from having
unbounded size, I'm adding a simple LRUCache implementation to sbt. An
important characteristic of the implementation of the cache is that when
entries are evicted, we run a callback to cleanup the entry. This allows
us to automatically cleanup any resources created by the entry.

This is a pretty naive implementation that uses an array of entries that
it manipulates as elements are removed/accessed. In general, I expect
these caches to be quite small <= 4 elements, so the storage overhead /
performance of the simple implementation should be quite good. If
performance ever becomes an issue, we can specialzed LRUCache.apply to
use a different implementation for caches with large limits.
2019-01-30 08:55:22 -08:00
eugene yokota 1e7564c408
Merge pull request #4499 from dwijnand/ParseKey-rare-failure
Avoid ParseKey failing due to homonymous axes
2018-12-22 14:29:59 -05:00
Dale Wijnand 3d924978c2
Add some matcher messaging to ParserSpec 2018-12-22 17:02:48 +00:00
Dale Wijnand e533bc93e8
Avoid ParseKey failing due to homonymous axes 2018-12-22 12:51:47 +00:00
Dale Wijnand 645f484184
Switch ParseKey to propertyWithSeed 2018-12-22 12:51:47 +00:00
Dale Wijnand 1f14a2c340
Split out ParseKey properties 2018-12-22 12:51:47 +00:00
Ethan Atkins bfffb4f489 Rename TestBuild.Keys to TestBuild.TestKeys
It drives me crazy that in intellij when I do the go to class task that
TestBuild.Keys comes up before Keys. Given how central Keys is to sbt,
it doesn't seem like a good idea to alias that particular class name.
2018-12-14 13:55:19 -08:00
Arnout Engelen ae932f7390 Discover Oracle JDK installed in /opt 2018-11-22 12:50:13 +01:00
Ethan Atkins aeadd8db72 Remove unneeded import 2018-10-08 13:59:40 -07:00
Eugene Yokota 2389106aa6 Use linesIterator for JDK 11 compat 2018-09-27 12:41:47 -04:00
kai-chi 3f1ce8b9a0 expand tilde prefix 2018-09-19 18:35:59 +02:00
Eugene Yokota 3e1dac5161 -Xfatal-warnings in most subprojects 2018-09-18 11:47:55 -04:00
Eugene Yokota f2bc786fd1 cleaning up a few compiler warnings 2018-09-17 22:30:14 -04:00
eugene yokota 04a4456dd0
Merge pull request #4313 from raboof/supportJdk11AndJavaHomeInCrossJava
Support discovering JDK 11 in JAVA_HOME for CrossJava
2018-09-17 12:34:31 -04:00
Eugene Yokota 4ff4f6e45e Update header 2018-09-14 04:53:36 -04:00
Eugene Yokota 590dc5e96d Merge branch '1.2.x' into wip/merge-1.2.x 2018-08-16 16:15:15 -04:00
Arnout Engelen bed2e11d59 Update test to reflect new WindowsDiscoverConfig ctor 2018-08-15 16:19:14 +02:00
Arnout Engelen b1fc7dc183 Support discovering JDK 11 in JAVA_HOME for CrossJava 2018-08-09 14:43:11 +02:00
Eugene Yokota 780ca366d8 Remove warnings about configuration
Fixes #4293
Ref #4231, #4065

This fixes the regression on sbt 1.2.0 that displays a lot of warnings about configurations.

The warning was added in #4231 in an attempt to fix #4065. This actually highlights somewhat loose usage of configurations among the builds in the wild, and the limitation on the current slash syntax implementation.

I think we can remove this warning for now, and try to fix #4065 by making slash syntax more robust. In particular, we need to memorize the mapping between the configuration name and Scala identifier across the entire build, and use that in the shell.
2018-08-06 00:22:57 -04:00
Eugene Platonov cc2159d565 add human readable total time 2018-07-21 15:56:48 -04:00
eugene yokota 8692952e91
Merge pull request #4245 from raboof/selectLatestJavaVersion
Select most recent JDK
2018-07-03 12:29:47 -04:00
Arnout Engelen 46693548d7 Add missing copyright header 2018-07-03 15:50:57 +02:00