-
Notifications
You must be signed in to change notification settings - Fork 26
/
Resolvers.scala
153 lines (125 loc) · 3.35 KB
/
Resolvers.scala
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* sbt -- Simple Build Tool
* Copyright 2011 Sanjin Sehic
*/
package sbt
import java.io.File
import java.net.URI
import BuildLoader.ResolveInfo
import RichURI.fromURI
object Resolvers
{
type Resolver = BuildLoader.Resolver
val local: Resolver = (info: ResolveInfo) => {
val uri = info.uri
val from = new File(uri)
val to = uniqueSubdirectoryFor(uri, in = info.staging)
if (from.isDirectory) Some {() => if(from.canWrite) from else creates(to) {IO.copyDirectory(from, to)}}
else None
}
val remote: Resolver = (info: ResolveInfo) => {
val url = info.uri.toURL
val to = uniqueSubdirectoryFor(info.uri, in = info.staging)
Some {() => creates(to) {IO.unzipURL(url, to)}}
}
val subversion: Resolver = (info: ResolveInfo) => {
def normalized(uri: URI) = uri.copy(scheme = "svn")
val uri = info.uri.withoutMarkerScheme
val localCopy = uniqueSubdirectoryFor(normalized(uri), in = info.staging)
val from = uri.withoutFragment.toASCIIString
val to = localCopy.getAbsolutePath
if (uri.hasFragment) {
val revision = uri.getFragment
Some {
() => creates(localCopy) {
run("svn", "checkout", "-q", "-r", revision, from, to)
}
}
} else
Some {
() => creates(localCopy) {
run("svn", "checkout", "-q", from, to)
}
}
}
val mercurial: Resolver = new DistributedVCS
{
override val scheme = "hg"
override def clone(from: String, to: File)
{
run("hg", "clone", "-q", from, to.getAbsolutePath)
}
override def checkout(branch: String, in: File)
{
run(Some(in), "hg", "checkout", "-q", branch)
}
}.toResolver
val git: Resolver = new DistributedVCS
{
override val scheme = "git"
override def clone(from: String, to: File)
{
run("git", "clone", from, to.getAbsolutePath)
}
override def checkout(branch: String, in: File)
{
run(Some(in), "git", "checkout", "-q", branch)
}
}.toResolver
abstract class DistributedVCS
{
val scheme: String
def clone(from: String, to: File)
def checkout(branch: String, in: File)
def toResolver: Resolver = (info: ResolveInfo) => {
val uri = info.uri.withoutMarkerScheme
val localCopy = uniqueSubdirectoryFor(normalized(uri), in = info.staging)
val from = uri.withoutFragment.toASCIIString
if (uri.hasFragment) {
val branch = uri.getFragment
Some {
() => creates(localCopy) {
clone(from, to = localCopy)
checkout(branch, in = localCopy)
}
}
} else Some {() => creates(localCopy) {clone(from, to = localCopy)}}
}
private def normalized(uri: URI) = uri.copy(scheme = scheme)
}
private lazy val onWindows = {
val os = System.getenv("OSTYPE")
val isCygwin = (os != null) && os.toLowerCase.contains("cygwin")
val isWindows = System.getProperty("os.name", "").toLowerCase.contains("windows")
isWindows && !isCygwin
}
def run(command: String*)
{
run(None, command: _*)
}
def run(cwd: Option[File], command: String*)
{
val result = Process(
if (onWindows) "cmd" +: "/c" +: command
else command,
cwd
) !;
if (result != 0)
error("Nonzero exit code (" + result + "): " + command.mkString(" "))
}
def creates(file: File)(f: => Unit) =
{
if (!file.exists)
try {
f
} catch {
case e =>
IO.delete(file)
throw e
}
file
}
def uniqueSubdirectoryFor(uri: URI, in: File) = {
in.mkdirs()
new File(in, Hash.halfHashString(uri.normalize.toASCIIString))
}
}