-
Notifications
You must be signed in to change notification settings - Fork 59
/
advance
executable file
·112 lines (98 loc) · 3.66 KB
/
advance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/local/bin/env -S scala-cli shebang --quiet
// to advance all projects:
// % ./advance
// to advance just selected ones:
// % ./advance scalacheck scalatest specs2
// "scala" is handled specially and updates nightly.properties
//> using scala 3.6.1
//> using option -source:future
//> using dep org.scala-lang.modules::scala-parallel-collections:1.0.4
//> using dep com.lihaoyi::os-lib:0.11.2
import scala.collection.parallel.CollectionConverters.* // for .par
def munge(l: String, replacement: String): String =
if (l.startsWith(""" uri: "https://github"""))
then s""" uri: "$replacement""""
else l
def getSha(repo: String, ref: String): String =
if (ref.matches("\\p{XDigit}{40}"))
then ref
else
import scala.sys.process.*
val cmd = s"git ls-remote $repo $ref"
def matches(s: String) =
s.containsSlice("refs/heads/") || s.containsSlice("refs/tags/")
Process(cmd).lazyLines.find(matches) match
case Some(line) =>
line.split("\\s").head
case None =>
throw new RuntimeException(s"$repo $ref")
// regexes for matching first line of each project's config
// note that we require an explicit tag or branch name,
// or a SHA (which must be the whole 40 characters).
// (dbuild defaults to `master`, but I prefer to make it explicit,
// to avoid confusion over whether the default is `master` or
// the repo's own default branch, which might be called something else)
object Regexes:
// I would prefer to just have these as top-level `val`s but the script
// deadlocks if I do that. some problem with parallel collections and
// script wrappers, I guess. I didn't investigate
val GitHub = """// (https://github.com/\S*.git)#(\S*)(\s*.*)""".r
val Ivy = """// ivy:.*""".r
import Regexes.*
def filesIn(dir: String): Seq[os.Path] =
os.list(os.pwd / dir).filter(_.ext == "conf").toSeq
val allFiles = filesIn("core") ++ filesIn("proj")
val selectedFiles =
if args.isEmpty then
allFiles
else
allFiles.filter(file => args.contains(file.baseName))
if selectedFiles.isEmpty && !args.contains("scala") then
println("no matches")
sys.exit(1)
for file <- selectedFiles.par
do
val lines = os.read.lines(file).to(Vector)
lines.head match
case GitHub(repo, ref, comment) =>
val uri = s"$repo#${getSha(repo, ref)}"
println(uri) // indicate progress
os.write.over(file,
lines.map(munge(_, uri)).mkString("", "\n", "\n"))
case bad =>
throw new IllegalArgumentException(bad)
// now handle "scala"
val formatter =
java.time.format.DateTimeFormatter.ofPattern(
"MMMM d, yyyy")
// returns: (version number, date)
def nightly(branch: String = "2.13.x"): (String, String) =
val sha =
os.proc("gh", "api", s"repos/scala/scala/git/ref/heads/$branch",
"--jq", ".object.sha")
.call().out.lines().head
val dateString =
os.proc("gh", "api", s"repos/scala/scala/branches/$branch",
"--jq", ".commit.commit.author.date")
.call().out.lines().head
val date = java.time.ZonedDateTime.parse(dateString).format(formatter)
val version =
os.proc("gh", "api",
"-H", "Accept: application/vnd.github.v3.raw",
s"repos/scala/scala/contents/build.sbt?ref=$branch")
.call().out.lines()
.collectFirst:
case s"""${_}Global / baseVersion${_}"$base"${_}""" =>
s"$base-bin-${sha.take(7)}"
.get
(version, date)
if args.isEmpty || args.contains("scala") then
val today =
java.time.LocalDate.now().format(formatter)
val (version, versionDate) = nightly()
val file = os.pwd / "nightly.properties"
os.write.over(file,
s"""|# $versionDate (latest as of $today)
|nightly=$version
|""".stripMargin)
print(os.read(file))