Commit Graph

7245 Commits

Author SHA1 Message Date
Ethan Atkins 32c2afaf2d Revert "revert doc"
It was only a matter of time before this erroneously got merged in.

This reverts commit 05aab1035a.
2019-06-04 16:45:16 -07:00
eugene yokota a2598d18d3
Merge pull request #4771 from dwijnand/issue-templates
Auto-label bug reports & delete old issue template
2019-06-04 12:42:15 -04:00
Dale Wijnand d48080adf1
Auto-label bug reports & delete old issue template 2019-06-04 08:01:18 +01:00
eugene yokota 1461f2c3d6
Merge pull request #4770 from eed3si9n/wip/bumpio
IO 1.3.0-M11
2019-06-04 01:29:51 -04:00
Eugene Yokota dabc4f8c8e IO 1.3.0-M11 2019-06-04 00:14:42 -04:00
eugene yokota 331271b052
Merge pull request #4761 from dwijnand/document-BuildStructure
Document helper functions in BuildStructure
2019-06-03 23:51:26 -04:00
eugene yokota e31fd3f082
Merge pull request #4765 from eatkins/watch-docs
Watch docs
2019-06-03 22:36:46 -04:00
eugene yokota ff94258116
Merge pull request #4769 from eatkins/java-reflection
Java reflection
2019-06-03 22:35:53 -04:00
Ethan Atkins 1ab666daf4 Change signature of pre watch methods
It makes the method parameters more clear if we pass in the ProjectRef
rather than the project name. We also don't lose information.
2019-06-03 17:41:08 -07:00
Ethan Atkins 05aab1035a revert doc 2019-06-03 17:35:01 -07:00
Ethan Atkins 70899e5cad Switch private[sbt] status of Reload objects
The Reload exception that I added in the sbt package really wasn't
intended to be public. It's only meant to be used by
checkMetaBuildSources, which the users shouldn't override. I put it in
the top package though because I wanted it to be next to FullReload. I
also am not sure why the Reload object in Watch was private[sbt], but
while writing documentation, I realized that users couldn't access it.
2019-06-03 17:35:01 -07:00
Ethan Atkins 7948408368 Simplify watch callbacks
While writing documentation for the watch subsystem, I realized that
it's awkward to configure watch to clear the screen before task
evaluation. To make this easier, I added a setting watchBeforeCommand
which is an arbitrary function that will run before the watch process
evaluates the command(s).

I also added helper functions for adding clear screen functionality.

I also realized that we weren't using the watchOnEnter or
watchOnExit callbacks anywhere. I had added these to support setting up
some state before watch starts and cleaning it up before it exits for
plugin authors. It makes sense to remove that functionality for 1.3.0
and only if a need presents itself re-add it in a later version of sbt.

I also made a few apis private[sbt] that I'm not sure about. Writing
documentation made me realize that some of these are redundant and/or
not ready for general consumption.
2019-06-03 17:35:01 -07:00
Ethan Atkins 3c81226ba9 Add sbt.nio.Watch to default imports
I realized writing documentation that it is a pain to not have Watch
available in build.sbt with an import.
2019-06-03 17:35:01 -07:00
Ethan Atkins 4f66b81e03 Fix parameters in watchTriggeredMessage 2019-06-03 17:35:01 -07:00
Ethan Atkins 2905373ff7 Use logger instead of directly printing to System.err 2019-06-03 17:35:01 -07:00
Ethan Atkins 67cbd6c50e Move watch default settings
I had previously set some of the watch settings at the global level and
some at the project level. While writing documentation for the new watch
subsystem, I realized that the defaults should be set globally so that
they can be overridden at the ThisBuild level.

I also moved watchTriggers to sbt.nio.Keys. It was an oversight that it
wasn't moved there in a5cefd45be.
2019-06-03 17:35:01 -07:00
Ethan Atkins 4193cc323d Remove leading semicolon from multi command help 2019-06-03 17:35:01 -07:00
Ethan Atkins 1b8f0ed20f Don't use filtered classpath
The classpath filter for test and run was added in #661 to ensure that
the classloaders were correctly isolated. That is no longer necessary
with the new layering strategies that are more precise about which jars
are exposed at each level. Using the filtered classloader was causing
the reflection used by spark to fail when using java 11.
2019-06-03 17:26:14 -07:00
Ethan Atkins ce6484f4b4 Set java source and target levels
Since sbt must run on jdk8, we should be setting the javac source and
target levels.
2019-06-03 17:26:14 -07:00
Ethan Atkins 014190a048 Add spark scripted test
This test ensures that a simple spark app will work with all of the
classloader layering strategies. Spark is an important part of the scala
ecosystem and heavily taxes classloading.

The test just checks that the app runs. I verified manually that the
first time that run is evaluated takes about 8 seconds regardless of the
layering strategy. It drops to 6 seconds with the ScalaLibrary strategy.
It drops to 1 seconds with AllLibraryJars.
2019-06-03 17:26:14 -07:00
Ethan Atkins 233307b696 Fix classpath filter in run
We were incorrectly building the dependency layer in the run task using
the raw jars from dependencyClasspath rather than the actual classpath
jars (which may be different if bgCopyClasspath is true -- which it is
by default). This was preventing spark from working with AllLibraryJars
because it would load its classes and resources from the coursier cache
but the classpath filter would reject the resources because they came
from the coursier cache instead of the classpath.
2019-06-03 17:26:14 -07:00
Ethan Atkins 625470cdd5 Make LayeredClassLoaders parallel capable
The docs for ClassLoader,
https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html
say that all non-hierarchical custom classloaders should be registered
as parallel capable. The docs also suggest that custom classloaders
should try to only override findClass so I reworked LayerdClassLoader to
only override findClass. I also added locking to the class loading to
make it safe for concurrent loading.

All of the custom classloaders besides LayeredClassLoader either
subclass URLClassLoader or LayeredClassLoader but don't override
loadClass. Because those two classloaders are parallel capable, the
subclasses should be as well. It isn't possible to make classloaders
that are implemented in scala parallel capable because scala 2 doesn't
support jvm static blocks (dotty does support this with an annotation).
To work around this, I re-worked some of the classloaders so that they
are either directly implemented in java or I subclassed a scala
implementation class in java.
2019-06-03 17:26:14 -07:00
Ethan Atkins cc8c66c66d Support java reflection with layered classloaders
Jave reflection did not work with layered classloaders if a dependency
attempted to load a class that was below the dependency layer in the
layered classloader hierarchy. The underlying problem was (in general) a
call to Class.forName somewhere. If the classloader parameter is not
specified, then Class.forName locates the ClassLoader for the caller
using reflection. It ultimately delegates to that ClassLoader's
loadClass method. With the previous LayeredClassLoader class, there was
no way for that classloader to access a URL that was below it in the
class loading hierarchy. I reworked LayeredClassLoader so that if it
fails to load the class, it will check the Thread's context classloader
and see if there are other LayeredClassLoader instances below it. If so,
it will then check if any of those classloaders would be able to load
the class by using findResource. If the descendant loader can load the
class, then we manually load it with findClass.
2019-06-03 14:21:59 -07:00
Ethan Atkins a3cde88db4 Fix runtime scala-reflect layer
For best caching performance, we want to use the scala-reflect.jar that
is found in the scala instance. Also, in the runtime configuration,
caching didn't work correctly because we filtered the scala reflect
library from the dependency jars. We really only wanted to filter out
the library jars.

It also was problematic to use a LayeredClassLoader for the scala
reflect layer because in a subsequent commit I add the capability for a
layered classloader to load classes from its descendant loaders. This
caused problems when the scala-reflect layer was a LayeredClassLoader.
Instead, I add the ScalaReflectClassLoader class for better reporting.
2019-06-03 14:21:59 -07:00
eugene yokota dc20eb2d4a
Merge pull request #4767 from sbt/eed3si9n-patch-1
Update issue templates
2019-06-03 11:38:39 -04:00
eugene yokota 796bb9e488 Update issue templates 2019-06-03 11:37:08 -04:00
Dale Wijnand 4e89e8ace5
Document helper functions in BuildStructure
Also define LoadedBuildUnit#projects & BuildUnit#thisRootProject, &
cleanup AttributeKey & BasicAttributeMap
2019-06-02 23:28:53 +01:00
eugene yokota df24c0d8aa
Merge pull request #4762 from eatkins/watch-commands
Watch commands
2019-06-02 16:41:56 -04:00
Ethan Atkins 87e6832f67 Make scripted watch/on-changes more robust
I noticed that sometimes this test hangs in ci. I think it may be
because sometimes the event for A got handled while the cache entry for
B.scala was invalidated. Because the test runs ~compile, the next run of
compile would then reset the cache entry for B.scala. The next run of
watchOnIteration invalidtes B.scala again, but this time to the same
hash, so it doesn't actually trigger a file input event. By changing the
content of B.scala every time, we ensure that it should still cause a
file event.

I haven't confirmed that this will fix the sporadic hangs because I
can't reproduce on my machine, but this change won't hurt.
2019-06-01 21:08:35 -07:00
Ethan Atkins df5f9ae3cb Support commands in continuous
I had previously not though there was much reason to support commands in
continuous builds. This was primarily because there were a number of
questions regarding semantics. Commands cannot have fileInputs
specifically assigned to them because they don't have an associated
scope. They also can arbitrarily modify state so what is the expectation
when running ~foo where foo is a command that, for example, replaces
itself. I settled on the following semantics:

1) Commands run in a continuous build cannot modify the sbt execution
   state which is to say that the state that is returned by continuous
   is the same that was passed in (unless a reload occurred or we exited
   the build with an exception)

2) Any global watchTriggers or fileInputs apply to a watched command.
   They automatically inherit any fileInputs that are queried when
   running tasks in a command. So, for example, ~+compile does what
   you'd expect.

The implementation is fairly straightforward. If we can successfully
parse a command, but we cannot parse a scopedKey from it, we assign it a
private ScopedKey. When computing the watch settings for that key, we
will select the global settings through delegation. This is how it picks
up the global watchTriggers.

To run the command, I had to rework the task evaluation portion because
a command may return a state with additional commands to run. The cross
build command works this way. We recursively run all of the commands
starting with the original until we run out of commands to run. As part
of this work, I was able to remove the three argument version of
Command.processCommand that I'd previously added to support my old
approach to evaluating commands. This was a nice bonus.

I added scripted tests that check that global watchTriggers are picked
up and that commands that delegate to a command that uses fileInputs
automatically pick up those inputs during the watch. I also added a test
that approximates the ~+compile use case and ensures that the failure
semantics are what we expect and that the task runs for all defined
scala versions.
2019-06-01 20:10:26 -07:00
Ethan Atkins b5ff4bda94 Optimize imports 2019-06-01 18:35:11 -07:00
Ethan Atkins 9466369211
Merge pull request #4758 from eatkins/play-run
Restore some legacy watch behavior for play run
2019-06-01 18:33:58 -07:00
Ethan Atkins cc52f88030
Merge branch 'develop' into play-run 2019-06-01 18:04:11 -07:00
eugene yokota b7fb0ca2a3
Merge pull request #4750 from eatkins/idle
Consolidate CommandChannel queues  (Reduce idle cpu usage)
2019-05-31 17:34:10 -04:00
Ethan Atkins 99211a45b2 Improve ServerSpec
I'm debugging some test failures on travis in ServerSpec and I noticed
that very often noisy stack traces were printed because the process was
not given time to exit. There also was a confusing error message that
said that it would wait 30 seconds for the process to start, but it
would actually wait 90 seconds. I rewrote waitForPortfile to use
durations instead of integers to make it more clear. I changed
process from type Future[Process] to Process. There was no reason to
make it a future. I also made waitForString a blocking function because
it also didn't need to be implemented with a future.
2019-05-31 09:34:04 -07:00
Ethan Atkins 6f7a824478 Reduce idle cpu usage
I noticed that sbt 1.3.0 was using more cpu when idling (either at the
shell or while waiting for file events) than 1.2.8. This was because I'd
reduced a number of timeouts to 2 milliseconds which was causing a
thread to keep waking up every 2 milliseconds to poll a queue. I thought
that this was cheaper than it actually is and drove the cpu utilization
to O(10%) of a cpu on my mac.

To address this, I consolidated a number of queues into a single queue
in CommandExchange and Continuous. In the CommandExchange case, I
reworked CommandChannel to have a register method that passes in a Queue
of CommandChannels. Whenever it appends an exec, it adds itself to the
queue. CommandExchange can then poll that queue directly and poll the
returned CommandChannel for the actual exec. Since the main thread is
blocking on this queue, it does not need to frequently wake up and can
just poll more or less indefinitely until a message is received. This
also reduces average latency compared to older versions of sbt since
messages will be processed almost as soon as they are received.

The continuous case is slightly more complicated because we are polling
from two sources, stdin and FileEventMonitor. In my ideal world, I'd
have a reactive api for both of those sources and they would just write
events to a shared queue that we could block on. That is nontrivial to
implement, so instead I consolidated the FileEventMonitor instances into
a single FileEventMonitor. Since there is now only one FileEventMonitor
queue, we can block on that queue for 30 milliseconds and the poll
stdin. This reduces cpu utilization to O(2%) on my machine while still
having reasonably low latency for key input events (the latency of file
events should be close to zero since we are usually polling the
FileEventMonitor queue when waiting).

I actually had a TODO about the FileEventMonitor change that this
resolves.
2019-05-31 09:34:04 -07:00
Ethan Atkins c748a5583e Restore some legacy watch behavior for play
I noticed that ~run in the Play plugin relied on the presence of the
ContinuousEventMonitor key. Rather than completely break that feature, I
re-added the ContinuousEventMonitor attribute to the state in a
continuous build. That being said, the play team does need to update
their plugin because reading from the console no longer works in 1.3.0 so the
user has to Ctrl-C to exit the watch. I think the best way for them to
fix this is to override the '~' command in their plugin and if the input
is 'run', then they do their custom thing, otherwise they delegate to
the default '~' command.
2019-05-31 09:33:34 -07:00
eugene yokota 73ebe34f71
Merge pull request #4755 from dwijnand/drop-the-pr-template
Drop the checkbox in the PR template
2019-05-31 11:06:05 -04:00
Ethan Atkins 3967171b99
Merge pull request #4753 from eatkins/meta-reload-check
Move meta build source check into Command.processCommand
2019-05-31 07:57:52 -07:00
Dale Wijnand 855880e62a
Also drop the checkbox in the issue template 2019-05-31 08:54:43 +01:00
Dale Wijnand b986749873
Drop the checkbox in the PR template
The intent was to bring prominence to the desires expressed in the
contributing guidelines.  But nowadays GitHub has ways in which it
informs users (e.g. "the contributing guidelines have changed since you
last contributed").  So I think we can drop this now.
2019-05-31 08:30:38 +01:00
Ethan Atkins 4158716b9a
Merge branch 'develop' into meta-reload-check 2019-05-30 21:59:02 -07:00
Ethan Atkins 499b6ab8be
Merge pull request #4754 from eatkins/layer-fixes
Layer fixes
2019-05-30 21:58:46 -07:00
Ethan Atkins d48f41dcf8
Merge branch 'develop' into layer-fixes 2019-05-30 21:08:59 -07:00
eugene yokota 08003f7afe
Merge pull request #4751 from eatkins/execution-context
Don't use global execution context
2019-05-30 23:17:58 -04:00
Ethan Atkins 5faf78af96 Add scala reflect layer
Not caching scala reflect is extremely painful if the build uses
scalatest. It adds O(1second) to my watch performance benchmarks. It
actually made sbt 1.3.0 much slower than 0.13.17
2019-05-30 17:30:14 -07:00
Ethan Atkins cf73bbbafc Fix ScalaLibrary again
I was benchmarking sbt with turbo mode on and found that tests weren't
running. This was because we were inadvertently excluding all of the
dependency jars from the dynamic classpath. I have no idea why the
scripted tests didn't catch this.

The scalatest scripted test didn't catch this because 'test' just
automaticaly succeeds if no test frameworks are found. To guard against
regression, I had to ensure that 'test' failed for every strategy if a
bad test file was present.
2019-05-30 17:30:14 -07:00
Ethan Atkins cda4713f89 Make AllLibraryJars a case object
This improves the toString and also allows it to be used in a pattern
match.
2019-05-30 17:30:14 -07:00
Ethan Atkins 525bf8fa3d Move meta build source check into Command.processCommand
We want to check the build sources before any command runs, not just
tasks. To achieve this, I moved the logic for checking for build source
changes to CommandProcess.processCommand. Also, @smarter had noticed
that if a user modified a build file and then ran reload, a warning
would be displayed about changed build sources even though they had just
ran reload. This was because running reload didn't update the previous
cache for checkBuildSources / fileInputStamps. I fixed that bug by
running 'checkBuildSources / changedInputFiles' instead of
'checkBuildSources' when the user runs reload.

I verified that after this change:

- If I changed a build file and ran 'show version' a warning was printed
  before it displayed the version. If I also set
  global / onChangedBuildSource := ReloadOnSourceChanges, it
  automatically reloaded before displaying the version.
- If I changed a build source and ran 'reload', followed by
  'show version', no warnings were ever displayed.

As an implementation detail, I had to add the Aggregation.suppressShow
attribute key. We set this key to true before checking the build
sources. Without this, log.success is called whenever we check the build
sources which is both confusing and noisy.
2019-05-30 15:55:21 -07:00
Ethan Atkins 3de3cc15cf Don't use global execution context
Because we are sharing the scala library classloader with test and run,
it is possible that sbt will be competing with for resources with the
test and run tasks when trying to get threads from the global execution
context. Also, by using our own execution context, we can shut it down
when sbt exits.

The motivation for this change is that I was looking at the active jvm
threads of an idle sbt process and noticed a bunch of global execution
context threads.
2019-05-30 14:30:31 -07:00