Skip to content

Commit f2c8847

Browse files
authored
Enable Scalafmt and format everything (#145)
This PR adds in 2 commits. One being a formatting commit since there is a `.scalafmt.conf` in this repo, but it was never enforced. The second commit adds a check in CI for formatting and also creates a `.git-blame-ignore-revs` file with the formatting commit in it. Pull request: #145
2 parents 16dd646 + c4a84b5 commit f2c8847

24 files changed

+1169
-1063
lines changed

.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Format the codebase for the first time
2+
b049841d5707d5bd87be516d8cda7be2a7585eae

.github/workflows/build.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ jobs:
4949

5050
- run: ./mill -i -k __.mimaReportBinaryIssues
5151

52+
check-formatting:
53+
runs-on: ubuntu-latest
54+
steps:
55+
- uses: actions/checkout@v3
56+
with:
57+
fetch-depth: 0
58+
59+
- uses: actions/setup-java@v3
60+
with:
61+
distribution: 'temurin'
62+
java-version: 8
63+
64+
- run: ./mill -i -k __.checkFormat
65+
5266
publish-sonatype:
5367
if: github.repository == 'com-lihaoyi/os-lib' && contains(github.ref, 'refs/tags/')
5468
needs: test

build.sc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import $ivy.`com.github.lolgab::mill-mima::0.0.13`
66
import mill._
77
import mill.define.{Task, Target}
88
import mill.scalalib._
9+
import mill.scalalib.scalafmt._
910
import mill.scalanativelib._
1011
import mill.scalalib.publish._
1112
import mill.scalalib.api.ZincWorkerUtil
@@ -124,7 +125,8 @@ trait SafeDeps extends ScalaModule {
124125
}
125126
}
126127

127-
trait OsLibModule extends CrossScalaModule with PublishModule with AcyclicModule with SafeDeps {
128+
trait OsLibModule extends CrossScalaModule with PublishModule with AcyclicModule with SafeDeps
129+
with ScalafmtModule {
128130
def publishVersion = VcsVersion.vcsState().format()
129131
def pomSettings = PomSettings(
130132
description = artifactName(),

os/src-jvm/ProcessOps.scala

Lines changed: 81 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,74 +5,76 @@ import java.util.concurrent.{ArrayBlockingQueue, Semaphore, TimeUnit}
55
import scala.annotation.tailrec
66

77
/**
8-
* Convenience APIs around [[java.lang.Process]] and [[java.lang.ProcessBuilder]]:
9-
*
10-
* - os.proc.call provides a convenient wrapper for "function-like" processes
11-
* that you invoke with some input, whose entire output you need, but
12-
* otherwise do not have any intricate back-and-forth communication
13-
*
14-
* - os.proc.stream provides a lower level API: rather than providing the output
15-
* all at once, you pass in callbacks it invokes whenever there is a chunk of
16-
* output received from the spawned process.
17-
*
18-
* - os.proc(...) provides the lowest level API: an simple Scala API around
19-
* [[java.lang.ProcessBuilder]], that spawns a normal [[java.lang.Process]]
20-
* for you to deal with. You can then interact with it normally through
21-
* the standard stdin/stdout/stderr streams, using whatever protocol you
22-
* want
23-
*/
8+
* Convenience APIs around [[java.lang.Process]] and [[java.lang.ProcessBuilder]]:
9+
*
10+
* - os.proc.call provides a convenient wrapper for "function-like" processes
11+
* that you invoke with some input, whose entire output you need, but
12+
* otherwise do not have any intricate back-and-forth communication
13+
*
14+
* - os.proc.stream provides a lower level API: rather than providing the output
15+
* all at once, you pass in callbacks it invokes whenever there is a chunk of
16+
* output received from the spawned process.
17+
*
18+
* - os.proc(...) provides the lowest level API: an simple Scala API around
19+
* [[java.lang.ProcessBuilder]], that spawns a normal [[java.lang.Process]]
20+
* for you to deal with. You can then interact with it normally through
21+
* the standard stdin/stdout/stderr streams, using whatever protocol you
22+
* want
23+
*/
2424
case class proc(command: Shellable*) {
2525
def commandChunks: Seq[String] = command.flatMap(_.value)
2626

2727
/**
28-
* Invokes the given subprocess like a function, passing in input and returning a
29-
* [[CommandResult]]. You can then call `result.exitCode` to see how it exited, or
30-
* `result.out.bytes` or `result.err.string` to access the aggregated stdout and
31-
* stderr of the subprocess in a number of convenient ways. If a non-zero exit code
32-
* is returned, this throws a [[os.SubprocessException]] containing the
33-
* [[CommandResult]], unless you pass in `check = false`.
34-
*
35-
* If you want to spawn an interactive subprocess, such as `vim`, `less`, or a
36-
* `python` shell, set all of `stdin`/`stdout`/`stderr` to [[os.Inherit]]
37-
*
38-
* `call` provides a number of parameters that let you configure how the subprocess
39-
* is run:
40-
*
41-
* @param cwd the working directory of the subprocess
42-
* @param env any additional environment variables you wish to set in the subprocess
43-
* @param stdin any data you wish to pass to the subprocess's standard input
44-
* @param stdout How the process's output stream is configured.
45-
* @param stderr How the process's error stream is configured.
46-
* @param mergeErrIntoOut merges the subprocess's stderr stream into it's stdout
47-
* @param timeout how long to wait in milliseconds for the subprocess to complete
48-
* @param check disable this to avoid throwing an exception if the subprocess
49-
* fails with a non-zero exit code
50-
* @param propagateEnv disable this to avoid passing in this parent process's
51-
* environment variables to the subprocess
52-
*/
53-
def call(cwd: Path = null,
54-
env: Map[String, String] = null,
55-
stdin: ProcessInput = Pipe,
56-
stdout: ProcessOutput = Pipe,
57-
stderr: ProcessOutput = os.Inherit,
58-
mergeErrIntoOut: Boolean = false,
59-
timeout: Long = -1,
60-
check: Boolean = true,
61-
propagateEnv: Boolean = true)
62-
: CommandResult = {
28+
* Invokes the given subprocess like a function, passing in input and returning a
29+
* [[CommandResult]]. You can then call `result.exitCode` to see how it exited, or
30+
* `result.out.bytes` or `result.err.string` to access the aggregated stdout and
31+
* stderr of the subprocess in a number of convenient ways. If a non-zero exit code
32+
* is returned, this throws a [[os.SubprocessException]] containing the
33+
* [[CommandResult]], unless you pass in `check = false`.
34+
*
35+
* If you want to spawn an interactive subprocess, such as `vim`, `less`, or a
36+
* `python` shell, set all of `stdin`/`stdout`/`stderr` to [[os.Inherit]]
37+
*
38+
* `call` provides a number of parameters that let you configure how the subprocess
39+
* is run:
40+
*
41+
* @param cwd the working directory of the subprocess
42+
* @param env any additional environment variables you wish to set in the subprocess
43+
* @param stdin any data you wish to pass to the subprocess's standard input
44+
* @param stdout How the process's output stream is configured.
45+
* @param stderr How the process's error stream is configured.
46+
* @param mergeErrIntoOut merges the subprocess's stderr stream into it's stdout
47+
* @param timeout how long to wait in milliseconds for the subprocess to complete
48+
* @param check disable this to avoid throwing an exception if the subprocess
49+
* fails with a non-zero exit code
50+
* @param propagateEnv disable this to avoid passing in this parent process's
51+
* environment variables to the subprocess
52+
*/
53+
def call(
54+
cwd: Path = null,
55+
env: Map[String, String] = null,
56+
stdin: ProcessInput = Pipe,
57+
stdout: ProcessOutput = Pipe,
58+
stderr: ProcessOutput = os.Inherit,
59+
mergeErrIntoOut: Boolean = false,
60+
timeout: Long = -1,
61+
check: Boolean = true,
62+
propagateEnv: Boolean = true
63+
): CommandResult = {
6364

6465
val chunks = new java.util.concurrent.ConcurrentLinkedQueue[Either[geny.Bytes, geny.Bytes]]
6566

6667
val sub = spawn(
67-
cwd, env,
68+
cwd,
69+
env,
6870
stdin,
6971
if (stdout ne os.Pipe) stdout
70-
else os.ProcessOutput.ReadBytes(
71-
(buf, n) => chunks.add(Left(new geny.Bytes(java.util.Arrays.copyOf(buf, n))))
72+
else os.ProcessOutput.ReadBytes((buf, n) =>
73+
chunks.add(Left(new geny.Bytes(java.util.Arrays.copyOf(buf, n))))
7274
),
7375
if (stderr ne os.Pipe) stderr
74-
else os.ProcessOutput.ReadBytes(
75-
(buf, n) => chunks.add(Right(new geny.Bytes(java.util.Arrays.copyOf(buf, n))))
76+
else os.ProcessOutput.ReadBytes((buf, n) =>
77+
chunks.add(Right(new geny.Bytes(java.util.Arrays.copyOf(buf, n))))
7678
),
7779
mergeErrIntoOut,
7880
propagateEnv
@@ -88,31 +90,33 @@ case class proc(command: Shellable*) {
8890
}
8991

9092
/**
91-
* The most flexible of the [[os.proc]] calls, `os.proc.spawn` simply configures
92-
* and starts a subprocess, and returns it as a `java.lang.Process` for you to
93-
* interact with however you like.
94-
*
95-
* To implement pipes, you can spawn a process, take it's stdout, and pass it
96-
* as the stdin of a second spawned process.
97-
*
98-
* Note that if you provide `ProcessOutput` callbacks to `stdout`/`stderr`,
99-
* the calls to those callbacks take place on newly spawned threads that
100-
* execute in parallel with the main thread. Thus make sure any data
101-
* processing you do in those callbacks is thread safe!
102-
*/
103-
def spawn(cwd: Path = null,
104-
env: Map[String, String] = null,
105-
stdin: ProcessInput = Pipe,
106-
stdout: ProcessOutput = Pipe,
107-
stderr: ProcessOutput = os.Inherit,
108-
mergeErrIntoOut: Boolean = false,
109-
propagateEnv: Boolean = true): SubProcess = {
93+
* The most flexible of the [[os.proc]] calls, `os.proc.spawn` simply configures
94+
* and starts a subprocess, and returns it as a `java.lang.Process` for you to
95+
* interact with however you like.
96+
*
97+
* To implement pipes, you can spawn a process, take it's stdout, and pass it
98+
* as the stdin of a second spawned process.
99+
*
100+
* Note that if you provide `ProcessOutput` callbacks to `stdout`/`stderr`,
101+
* the calls to those callbacks take place on newly spawned threads that
102+
* execute in parallel with the main thread. Thus make sure any data
103+
* processing you do in those callbacks is thread safe!
104+
*/
105+
def spawn(
106+
cwd: Path = null,
107+
env: Map[String, String] = null,
108+
stdin: ProcessInput = Pipe,
109+
stdout: ProcessOutput = Pipe,
110+
stderr: ProcessOutput = os.Inherit,
111+
mergeErrIntoOut: Boolean = false,
112+
propagateEnv: Boolean = true
113+
): SubProcess = {
110114
val builder = new java.lang.ProcessBuilder()
111115

112116
val baseEnv =
113117
if (propagateEnv) sys.env
114118
else Map()
115-
for ((k, v) <- baseEnv ++ Option(env).getOrElse(Map())){
119+
for ((k, v) <- baseEnv ++ Option(env).getOrElse(Map())) {
116120
if (v != null) builder.environment().put(k, v)
117121
else builder.environment().remove(k)
118122
}
@@ -123,7 +127,7 @@ case class proc(command: Shellable*) {
123127
val commandStr = cmdChunks.mkString(" ")
124128
lazy val proc: SubProcess = new SubProcess(
125129
builder
126-
.command(cmdChunks:_*)
130+
.command(cmdChunks: _*)
127131
.redirectInput(stdin.redirectFrom)
128132
.redirectOutput(stdout.redirectTo)
129133
.redirectError(stderr.redirectTo)

os/src-jvm/ResourcePath.scala

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import java.io.InputStream
44

55
import scala.language.implicitConversions
66

7-
object ResourcePath{
7+
object ResourcePath {
88
def resource(resRoot: ResourceRoot) = {
99
new ResourcePath(resRoot, Array.empty[String])
1010
}
1111
}
1212

1313
/**
14-
* Represents path to a resource on the java classpath.
15-
*
16-
* Classloaders are tricky: http://stackoverflow.com/questions/12292926
17-
*/
18-
class ResourcePath private[os](val resRoot: ResourceRoot, segments0: Array[String])
19-
extends BasePathImpl with ReadablePath with SegmentedPath {
20-
def getInputStream = resRoot.getResourceAsStream(segments.mkString("/")) match{
14+
* Represents path to a resource on the java classpath.
15+
*
16+
* Classloaders are tricky: http://stackoverflow.com/questions/12292926
17+
*/
18+
class ResourcePath private[os] (val resRoot: ResourceRoot, segments0: Array[String])
19+
extends BasePathImpl with ReadablePath with SegmentedPath {
20+
def getInputStream = resRoot.getResourceAsStream(segments.mkString("/")) match {
2121
case null => throw ResourceNotFoundException(this)
2222
case stream => stream
2323
}
@@ -27,7 +27,7 @@ class ResourcePath private[os](val resRoot: ResourceRoot, segments0: Array[Strin
2727
def lastOpt = segments0.lastOption
2828
override def toString = resRoot.errorName + "/" + segments0.mkString("/")
2929
protected[this] def make(p: Seq[String], ups: Int) = {
30-
if (ups > 0){
30+
if (ups > 0) {
3131
throw PathError.AbsolutePathOutsideRoot
3232
}
3333
new ResourcePath(resRoot, p.toArray[String])
@@ -37,51 +37,48 @@ class ResourcePath private[os](val resRoot: ResourceRoot, segments0: Array[Strin
3737
var newUps = 0
3838
var s2 = base.segments
3939

40-
while(!segments0.startsWith(s2)){
40+
while (!segments0.startsWith(s2)) {
4141
s2 = s2.dropRight(1)
4242
newUps += 1
4343
}
4444
new RelPath(segments0.drop(s2.length), newUps)
4545
}
4646

47-
4847
def startsWith(target: ResourcePath) = {
4948
segments0.startsWith(target.segments)
5049
}
5150

5251
}
5352

5453
/**
55-
* Thrown when you try to read from a resource that doesn't exist.
56-
* @param path
57-
*/
54+
* Thrown when you try to read from a resource that doesn't exist.
55+
* @param path
56+
*/
5857
case class ResourceNotFoundException(path: ResourcePath) extends Exception(path.toString)
5958

60-
6159
/**
62-
* Represents a possible root where classpath resources can be loaded from;
63-
* either a [[ResourceRoot.ClassLoader]] or a [[ResourceRoot.Class]]. Resources
64-
* loaded from classloaders are always loaded via their absolute path, while
65-
* resources loaded via classes are always loaded relatively.
66-
*/
67-
sealed trait ResourceRoot{
60+
* Represents a possible root where classpath resources can be loaded from;
61+
* either a [[ResourceRoot.ClassLoader]] or a [[ResourceRoot.Class]]. Resources
62+
* loaded from classloaders are always loaded via their absolute path, while
63+
* resources loaded via classes are always loaded relatively.
64+
*/
65+
sealed trait ResourceRoot {
6866
def getResourceAsStream(s: String): InputStream
6967
def errorName: String
7068
}
71-
object ResourceRoot{
69+
object ResourceRoot {
7270
private[this] def renderClassloader(cl: java.lang.ClassLoader) = {
7371
cl.getClass.getName + "@" + java.lang.Integer.toHexString(cl.hashCode())
7472
}
7573
implicit def classResourceRoot(cls: java.lang.Class[_]): ResourceRoot = Class(cls)
76-
case class Class(cls: java.lang.Class[_]) extends ResourceRoot{
74+
case class Class(cls: java.lang.Class[_]) extends ResourceRoot {
7775
def getResourceAsStream(s: String) = cls.getResourceAsStream(s)
7876
def errorName = renderClassloader(cls.getClassLoader) + ":" + cls.getName
7977
}
8078
implicit def classLoaderResourceRoot(cl: java.lang.ClassLoader): ResourceRoot = ClassLoader(cl)
81-
case class ClassLoader(cl: java.lang.ClassLoader) extends ResourceRoot{
79+
case class ClassLoader(cl: java.lang.ClassLoader) extends ResourceRoot {
8280
def getResourceAsStream(s: String) = cl.getResourceAsStream(s)
8381
def errorName = renderClassloader(cl)
8482
}
8583

8684
}
87-

0 commit comments

Comments
 (0)