Commit Graph

2200 Commits

Author SHA1 Message Date
Ethan Atkins 6da876cbe7 Remove unneeded string interpolation 2019-03-30 16:38:44 -07:00
Ethan Atkins 81481a8af5 Disable supershell in CI
The supershell output is distracting in CI. I added a system property,
sbt.ci, to explicitly set whether or not sbt is running in a ci build.
It was not at all obvious to me if the BUILD_NUMBER or CI environment
variables were set on travis or appveyor.
2019-03-30 11:51:47 -07:00
eugene yokota ca5f978df4
Merge pull request #4589 from eed3si9n/wip/metabuild_fix
Exclude all sbt modules from metabuild resolution
2019-03-30 11:52:25 -04:00
Eugene Yokota 33e648473f Exclude major sbt modules from metabuild resolution
Fixes #4582

#4443 introduced a perf enhacement of exluding sbt out of the metabuild, and instead appending the list of JARs resolved by the sbt launcher to the classpath.
This strategy worked in most cases, but it seems like some plugins are explicitly depending on IO module. In those cases, old IO would come before the new IO in the classpath ordering, resulting to "Symbol X is missing from classpath" error.
This fixes the issue by excluding all modules whose organization is `org.scala-sbt`.

As an escape hatch, I am adding a new key `reresolveSbtArtifacts`, which can be used to opt out of this behavior.
2019-03-29 21:34:49 -04:00
Ethan Atkins 6b82a8d07e Don't use usingTerminal
The usingTerminal method synchronizes the JLine object which can lead to
deadlock if multiple threads call it. When we just to want to read the
attributes of the terminal, but not modify it, there doesn't seem to be
any reason to use a lock.
2019-03-28 20:37:49 -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
eugene yokota de5c0434df
Merge pull request #4576 from eed3si9n/wip/trace
output Chrome traces on -Dsbt.traces=true
2019-03-25 17:21:59 -04:00
Eugene Yokota adfb2ece1a install official sbt based on project/build.properties 2019-03-25 02:10:48 -04:00
Eugene Yokota a713a62d12 widen scopes for classLoaderLayeringStrategy
Fixes #4574

This defines the `classLoaderLayeringStrategy` key at `Global` and `Zero / Test` level, and uses the scope delegation to pick them out from `test`.
2019-03-24 14:49:37 -04:00
Jason Zaugg 3600c97f1f WIP output Chrome trace format 2019-03-23 18:42:00 -04:00
Ethan Atkins f26afe6681 Return (Path, FileAttributes) instead of Stamped.File
I realized that Stamped.File was a bad interface that was really just an
implementation detail of external hooks. I updated the
GlobLister.{ all, unique } methods to return Seq[(Path, FileAttributes)]
rather than Stamped.File which is a much more natural api and one I
could see surviving the switch to nio based apis planned for
1.4.0/2.0.0. I also added a simple scripted test for glob listing. The
GlobLister.all method is implicitly tested all over the place since the
compile task uses it, but it's good to have an explicit test.
2019-03-22 09:32:36 -07:00
Ethan Atkins c3e0e117e6 Do not use caching repository by default
The caching repository does not work universally so set the default to
always poll. This is still faster than in sbt 1.2.x because of
performance improvements that I added for listing directories.
2019-03-22 09:32:36 -07:00
Ethan Atkins 467ece1ba1 Temporarily make FileTree.Repository public
This should not be exposed to users but will be for M1.
2019-03-22 09:32:36 -07:00
Ethan Atkins d231d7d9ec Rename FileCacheEntry to FileAttributes
I decided that FileCacheEntry was a bad name because the methods did not
necessarily have anything to do with caching. Moreover, because it is
exposed in a public interface, it shouldn't be in the internal package.
2019-03-22 09:32:36 -07:00
Ethan Atkins be94b25d68 Add Event trait to FileCacheEntry
Rather than exposing the FileEventMonitor.Event types, which are under
active development in the io repo, I am adding a new event trait to
FileCacheEntry. This trait doesn't expose any internal implementation
details.
2019-03-22 09:32:36 -07:00
Ethan Atkins 86200345e1 Don't expose TypedPath to users
I've decided I don't like the TypedPath interface so I'm not going to
expose it publicly.
2019-03-22 09:32:36 -07:00
Ethan Atkins fac6e0d9a0 Make file repository apis private[sbt]
I haven't fully settled on these interfaces yet so they shouldn't be publicly
exposed in the sbt api.
2019-03-22 09:32:36 -07:00
Ethan Atkins e3625ca8b0 Fix repository setup on windows
Windows io really doesn't handle concurrent readers and writers all that
well. Using the LegacyFileTreeRepository was problematic in windows
scripted tests because even though the repository implementation did not
use the cache in its list methods, it did persistently monitor the
directories that were registered. The monitor has to do a lot of
io on a background thread to maintain the cache. This caused io
contention that would cause IO.createDirectory to fail with an obscure
AccessDeniedException. The way to avoid this is to prevent the
background io from occurring at all.

I don't necessarily think this will impact most users running sbt
interactively with a cache, but it did cause scripted tests to fail. For
that reason I made the default in non-interactive/shell use cases on
windows to be a PollingFileRepository which never monitors the file
system except when we are in a watch. The LegacyFileTreeRepository works
fine on mac and linux which have a more forgiving file system.

To make this work, I had to add FileManagement.toMonitoringRepository.
There are now two kinds of repositories that cannot monitor on their
own: HybridPollingFileTreeRepository and PollingFileRepository. The
FileManagement.toMonitoringRepository makes a new repository that turns
on monitoring for those two repository types and disables the close
method on all other repositories so that closing the FileEventMonitor
does not actually close the global file repository.
2019-03-22 09:32:35 -07:00
Ethan Atkins b0c5e00c7c Reimplement clean
I ran into a couple of issues with the clean implementation. I changed
the logging to print to stdout instead of streams if enabled. I also
added a helper, Clean.deleteContents that recursively deletes all of the
contents of a directory except for those that match the exclude filter
parameter.

Using a normal logger was a bad idea because we are actually deleting
the target/streams directory when running clean.

The previous implementation worked by getting the full list of files to
delete, reverse sorting it and then deleting every element in the list.
While this can work well it many circumstances, if the directory is
still being written to during the recursive deletion, then we could miss
files that were added after we fetched all of the files. The new version
lazily lists the subdirectories as needed.
2019-03-22 09:32:35 -07:00
Ethan Atkins de3c09f99d Move clean task implementation to Clean.scala
The Defaults.scala file has a lot going on. I am trying to generally
follow the pattern of implementing the default task implementation in a
different file and just adding the appropriate declarations in
Defaults.scala.
2019-03-22 09:32:35 -07:00
Ethan Atkins 172c8e9a0b Support custom clean tasks
This rewroks the cleanTask so that it only removes a subset of the
files in the target directory. To do this, I add a new task, outputs,
that returns the glob representation of the possible output files for
the task. It must be a task because some outputs will depend on streams.
For each project, the default outputs are all of the files in
baseDirectory / target.

Long term, we could enhance the clean task to be automatically generated
in any scope (as an input task). We could then add the option for the
task scoped clean to delete all of the transitive outputs of the class.
That is beyond the scope of this commit, however.

I copied the scripted tests from #3678 and added an additional test to
make sure that the manage source directory was explicitly cleaned.
2019-03-22 09:32:35 -07:00
Ethan Atkins c77a26e832 Update clean task to use globs
The clean task is unreasonably slow because it does a lot of redundant
io. In this commit, I update clean to be implemented using globs. This
allows us to (optionally) route io through the file system cache. There
is a significant performance improvement to this change. Currently,
running clean on the sbt project takes O(6 seconds) on my machine. After
this change, it takes O(1 second).

To implement this, I added a new setting cleanKeepGlobs to replace
cleanKeepFiles. I don't think that cleanKeepFiles returning Seq[File] is
a big deal for performance because, by default, it just contains the
history file so there isn't much benefit to accessing a single file
through the cache. The reason I added the setting was more for
consistency and to help push people towards globs in their own task
implementations.

Part of the performance improvement comes from inverting the problem.
Before we would walk the file system tree from the base and recursively
delete leafs and nodes in a depth first traversal. Now we collect all of
the files that we are interested in deleting in advance. We then sort
the results lexically by path name and then perform the deletions in
that order. Because children will always comes first in this scheme,
this will generally allow us to delete a directory.

There is an edge case that if files are created in a subdirectory after
we've created the list to delete, but before the subdirectory is
deleted, then that subdirectory will not be deleted. In general, this
will tend to impact target/streams because writes occur to
target/streams during traversal. I don't think this really matters for
most users. If the target directory is being concurrently modified with
clean, then the user is doing something wrong.

To ensure legacy compatibility, I re-implement cleanKeepFiles to return
no files. Any plugin that was appending files to the cleanKeepFiles task
with `+=` or `++=` will continue working as before because I explicitly
add those files to the list to delete. I updated the actions/clean-keep
scripted test to use both cleanKeepFiles and cleanKeepGlobs to ensure
both tasks are correctly used.

Bonus: add debug logging of all deleted files
2019-03-22 07:53:41 -07:00
Ethan Atkins 571b179574 Add dsl for collecting globs
Right now, the sbt.internal.io.Source is something of a second class
citizen within sbt. Since sbt 0.13, there have been extension classes
defined that can convert a file to a PathFinder but no analog has been
introduced for sbt.internal.io.Source.

Given that sbt.internal.io.Source was not really intended to be part of
the public api (just look at its package), I think it makes sense to
just replace it with Glob. In this commit, I add extension
methods to Glob and Seq[Glob] that make it possible to easily
retrieve all of the files for a particular Glob within a task. The
upshot is that where previously, we'd have had to write something like:

watchSources += Source(baseDirectory.value / "src" / "main" / "proto", "*.proto", NothingFilter)

now we can write

watchGlobs += baseDirectory.value / "src" / "main" / "proto" * "*.proto"

Moreover, within a task, we can now do something like:
foo := {
  val allWatchGlobs: Seq[File] = watchGlobs.value.all
  println(allWatchSources.mkString("all watch source files:\n", "\n", ""))
}
Before we would have had to manually retrieve the files.

The implementation of the dsl uses the new GlobExtractor class which
proxies file look ups through a FileTree.Repository. This makes it so
that, by default, all file i/o using Sources will use the default
FileTree.Repository. The default is a macro that returns
`sbt.Keys.fileTreeRepository.value: @sbtUnchecked`. By doing it this
way, the default repository can only be used within a task definition
(since it delegates to `fileTreeRepository.value`). It does not,
however, prevent the user from explicitly providing a
FileTree.Repository instance which the user is free to instantiate
however they wish.

Bonus: optimize imports in Def.scala and Defaults.scala
2019-03-22 07:53:41 -07:00
Ethan Atkins d0310cc866 Rework FileTreeRepository configuration
The FileTreeViewConfig abstraction that I added was somewhat unwieldy
and confusing. The original intention was to provide users with a lot of
flexibility in configuring the global file tree repository used by sbt.
I don't think that flexibility is necessary and it was both conceptually
complicated and made the implementation complex. In this commit, I add a
new boolean flag enableGlobalCachingFileTreeRepository that toggles
which kind of FileTreeRepository to use globally.

There are actually three kinds of repositories that could be returned:
1) FileTreeRepository.default -- this caches the entire file system
   tree it hooks into the cache's event callbacks to create a file event
   monitor. It will be used if enableGlobalCachingFileTreeRepository is
   true and Global / pollingGlobs := Nil
2) FileTreeRepository.hybrid -- similar to FileTreeRepository.default
   except that it will not cache any files that are included in
   Global / pollingGlobs. It will be used if
   enableGlobalCachingFileTreeRepository is true and
   Global / pollingGlobs is non empty
3) FileTreeRepository.legacy -- does not cache any of the file system
   tree, but does maintain a persistent file monitoring process that is
   implemented with a WatchServiceBackedObservable. Because it doesn't
   poll, in general, it's ok to leave the monitoring on in the
   background. One reason to use this is that if there are any issues
   with the cache being unable to accurately mirror the underlying file
   system tree, this repository will always poll the file system
   whenever sbt requests the entries for a given glob. Moreover, the
   file system tree implementation is very similar to the implementation
   that was used in 1.2.x so this gives users a way to almost fully opt
   back in to the old behavior.
2019-03-22 07:53:41 -07:00
Ethan Atkins 792fb91737 Avoid deprecated Alternative class 2019-03-22 07:53:41 -07:00
Ethan Atkins f7f7addff7 Bump io
This new version of io breaks source and binary compatibility everywhere
that uses the register(path: Path, depth: Int) method that is defined on
a few interfaces because I changed the signature to register(glob:
Glob). I had to convert to using a glob everywhere that register was
called.

I also noticed a number of places where we were calling .asFile on a
file. This is redundant because asFile is an extension method on File
that just returns the underlying file.

Finally, I share the IOSyntax trait from io in AllSyntax. There was more
or less a TODO suggesting this change. The one hairy part is the
existence of the Alternative class. This class has unfortunately somehow
made it into the sbt package object. While I doubt many plugins are
using this, it doesn't seem worth breaking binary compatibility to get
rid of it. The issue is that while Alternative is defined private[sbt],
the alternative method in IOSyntax is public, so I can't get rid of
Alternative without breaking binary compatibility.

I'm not deprecating Alternative for now because the sbtProj still has
xfatal warnings on. I think in many, if not most, cases, the Alternative
class makes the code more confusing as is often the case with custom
operators. The confusion is mitigated if the abstraction is used only in
the file in which it's defined.
2019-03-22 07:53:41 -07:00
Ethan Atkins e536c4ac39 Remove unused local variable 2019-03-20 11:22:21 -07:00
Eugene Yokota 86abe3ed60 open up ExecuteProgress, and adds a few keys
Fixes #4461

This opens up ExecuteProgress API that's been around under private[sbt].
Since the state passing mechanism hasn't been used, I got rid of it.

The build user can configure the build using two keys Boolean `taskProgress` and `State => Seq[TaskProgress]` `progressReports`. `useSuperShell` is lightweight key on/off switch for the super shell that can be used as follows:

```scala
Global / SettingKey[Boolean]("useSuperShell") := false
```
2019-03-19 00:42:46 -04:00
Eugene Yokota cd1d2e0994 Util 1.3.0-M5 2019-03-08 19:18:53 -05:00
Eugene Yokota 3cd8cc4e86 Make sure progress thread gets shutdown 2019-02-26 05:10:18 -05:00
Ethan Atkins fcd24ba7cd Reduce command polling period
The only thing this function does is poll a queue and check a deadline.
There is no need to put such a large sleep duration in.
2019-02-14 21:13:07 -08:00
Ethan Atkins c37f2607f1 Lint CommandExchange.scala
Clears out intellij warnings.
2019-02-14 21:09:44 -08:00
Ethan Atkins faf6348a16 Run gc when idle
I often find that when I run a command it takes a long time to start up
because sbt triggers a full gc. To improve the ux, I update the command
exchange to run full gc only once while it's waiting for a command to
run and only after the user has been idle for at least one minute.

Bonus: optimize imports
2019-02-14 21:09:17 -08:00
Guillaume Martres 85f91e76ca Remove Dotty handling in scalaInstance
sbt-dotty 0.3.0 (https://github.com/lampepfl/dotty/pull/5835) sets
`managedScalaInstance := false` and does everything by itself, so this
isn't needed anymore.
2019-02-12 23:30:45 +01:00
eugene yokota fbadfabfe2
Merge pull request #4538 from eatkins/compiler-cache
Clear compiler cache in clearCaches
2019-02-04 10:27:14 -05:00
eugene yokota e73d1fb7c6
Merge pull request #4537 from eatkins/allow-watch-loops
Allow watch loops
2019-02-04 10:25:11 -05:00
Ethan Atkins e8af828c73 Add FileCacheEntry
Previously, we were leaking the internal details of incremental
compilation to users by defining FileTree(DataView|Repository)[Stamp].
To avoid this, I introduce the new class FileCacheEntry that is quite
similar to Stamp except defined using scala Options rather than java
Optionals. The implementation class just delegates to an actual Stamp
and I provided a private[sbt] ops class that adds a
method `stamp` to FileCacheEntry. This will usually just extract the
stamp from the implementation class. This allows us to use
FileCacheEntry almost interchangeably with Stamp while still avoiding
exposing users to Stamp.
2019-02-02 16:03:59 -08:00
Ethan Atkins ba0494df14 Stop Stamped from inheriting File and TypedPath
In the FileTreeDataView use case, we were previously working with
FileTreeDataView[Stamped], which actually contained a lot of redundant
information because FileTreeDataView.Entry[_] has a toTypedPath method
that could be used to read the path related fields in Stamped. Instead,
we can just return the Stamp itself in FileTreeDataView.list* methods
and convert to Stamped.File where needed (i.e. in ExternalHooks).

Also move BasicKeys.globalFileTreeView to Keys since it isn't actually
used in the main-command project.
2019-02-02 12:22:57 -08:00
Ethan Atkins 0bdc30b60b Rename StampedFile to Stamped 2019-02-02 12:22:57 -08:00
Ethan Atkins f44e2a2e74 Clear compiler cache in clearCaches
Resident compilation actually works pretty well most of the time*,
but if there ever is an issue with the cached compilation, we should be
able to easily clear the cache.

* I've only had issues when package objects are involved
2019-02-02 12:20:32 -08:00
Ethan Atkins 116d2ae815 Use ? instead of extracting state
I was unaware of the '?' method when I wrote this.
2019-02-01 18:01:56 -08:00
Ethan Atkins 2ef97768a0 Don't attempt to prevent certain watch loops
If the managedSources task writes into an unmanaged source directory,
that would cause an infinite loop. I don't think it's worth doing out of
band task execution to try and prevent this.
2019-02-01 18:01:56 -08:00
Ethan Atkins 92807869ea Fix community build
The community build was broken for some projects because I broke builds
that relied on the unscoped definition of `runner`. To preserve legacy
behavior, I restore the old unscoped behavior and append the new scoped
runners that used the layered classloaders. This makes more sense
because the layered classloaders were specifically designed for the
Runtime and Test configurations and may not make sense in other
contexts.
2019-01-30 20:54:08 -08:00
Ethan Atkins ba3ff8198d Remove unneeded parens in Definition.scala 2019-01-30 10:46:00 -08:00
Ethan Atkins 06a153278f Cleanup cache when CommandExchange shuts down
I noticed that sometimes when running scripted tests that I'd run out of
metaspace. I believe that this may be due to the caffeine cache leaking
classloaders. Regardless, it's a good idea to clear the cache whenever
we shutdown the command exchange or reload the state.
2019-01-30 10:45:22 -08:00
Ethan Atkins 0a4fbc9f5a Set classLoaderLayeringStrategy in relevant configs
Previously, the ClassLoaderLayeringStrategy was set globally. This
didn't really make sense because the Runtime and Test configs had
different strategies available (Test being a superset of Runtime).
Instead, we now set the layering strategy in the Runtime and Test
configurations directly. In doing this, we can eliminate the Default
ClassLoaderLayeringStrategy. Previously this had existed so that we
could set the layering strategy globally and have it do the right thing
in both test and runtime.

To implement this, I factored out the logic for generating the layered
classloader in the test task and shared it with the runtime task. I did
this because I realized that Test / run is a thing. Previously I had
been operating under the assumption that the runner would never include
the test dependencies. Once I realized this, it made sense to combine
the logic in both tasks.

As a bonus, I only allow the layering strategies that explicitly make
sense to be set in each configuration. If the user sets an invalid
strategy, an error will be thrown that specifies the valid strategies
for the task.

I also added ScalaInstance as an option for the runtime layer. It was an
oversight that this was left out.
2019-01-30 08:55:22 -08:00
Ethan Atkins 3a211710f9 Rename some layering related fields/classes
In code review, @eed3si9n suggested that I switch to a more verbose and
descriptive naming scheme. In addition to trying to make layers more
descriptive, I also made the various layer case objects extend the
relevant layers so it's more clear what the layer should look like.
2019-01-30 08:55:22 -08:00
Ethan Atkins 1ca6b97de2 JDK 11 fixes
In JDK 11, String.lines returns java.util.stream.Stream[String]. Switch
to linesIterator instead.
2019-01-30 08:55:22 -08:00