@@ -23,29 +23,33 @@ import TSCUtility
23
23
import Workspace
24
24
25
25
extension SwiftPackageCommand {
26
- struct Add : SwiftCommand {
26
+ struct AddDependency : SwiftCommand {
27
27
package static let configuration = CommandConfiguration (
28
- abstract: " Add a dependency to the package manifest " )
28
+ abstract: " Add a package dependency to the manifest " )
29
+
30
+ @Argument ( help: " The URL or directory of the package to add " )
31
+ var dependency : String
29
32
30
33
@OptionGroup ( visibility: . hidden)
31
34
var globalOptions : GlobalOptions
32
35
33
- @Option ( help: " The branch to depend on " )
34
- var branch : String ?
36
+ @Option ( help: " The exact package version to depend on " )
37
+ var exact : Version ?
35
38
36
- @Option ( help: " The minimum version requirement " )
37
- var fromVersion : String ?
39
+ @Option ( help: " The specific package revision to depend on " )
40
+ var revision : String ?
38
41
39
- @Option ( help: " The exact version requirement " )
40
- var exactVersion : String ?
42
+ @Option ( help: " The branch of the package to depend on " )
43
+ var branch : String ?
41
44
42
- @Option ( help: " A specific revision requirement " )
43
- var revision : String ?
45
+ @Option ( help: " The package version to depend on (up to the next major version) " )
46
+ var from : Version ?
44
47
45
- // FIXME: range option
48
+ @Option ( help: " The package version to depend on (up to the next minor version) " )
49
+ var upToNextMinorFrom : Version ?
46
50
47
- @Argument ( help: " The URL or directory of the package to add " )
48
- var url : String
51
+ @Option ( help: " Specify upper bound on the package version range (exclusive) " )
52
+ var to : Version ?
49
53
50
54
func run( _ swiftCommandState: SwiftCommandState ) throws {
51
55
let workspace = try swiftCommandState. getActiveWorkspace ( )
@@ -73,26 +77,59 @@ extension SwiftPackageCommand {
73
77
}
74
78
}
75
79
76
- let identity = PackageIdentity ( url: . init( url) )
80
+ let identity = PackageIdentity ( url: . init( dependency) )
81
+
82
+ // Collect all of the possible version requirements.
83
+ var requirements : [ PackageDependency . SourceControl . Requirement ] = [ ]
84
+ if let exact {
85
+ requirements. append ( . exact( exact) )
86
+ }
77
87
78
- // Figure out the version requirement.
79
- let requirement : PackageDependency . SourceControl . Requirement
80
88
if let branch {
81
- requirement = . branch( branch)
82
- } else if let fromVersion {
83
- requirement = . revision( fromVersion)
84
- } else if let exactVersion {
85
- requirement = . exact( try Version ( versionString: exactVersion) )
89
+ requirements. append ( . branch( branch) )
90
+ }
91
+
92
+ if let revision {
93
+ requirements. append ( . revision( revision) )
94
+ }
95
+
96
+ if let from {
97
+ requirements. append ( . range( . upToNextMajor( from: from) ) )
98
+ }
99
+
100
+ if let upToNextMinorFrom {
101
+ requirements. append ( . range( . upToNextMinor( from: upToNextMinorFrom) ) )
102
+ }
103
+
104
+ if requirements. count > 1 {
105
+ throw StringError ( " must specify at most one of --exact, --branch, --revision, --from, or --up-to-next-minor-from " )
106
+ }
107
+
108
+ guard let firstRequirement = requirements. first else {
109
+ throw StringError ( " must specify one of --exact, --branch, --revision, --from, or --up-to-next-minor-from " )
110
+ }
111
+
112
+ let requirement : PackageDependency . SourceControl . Requirement
113
+ if case . range( let range) = firstRequirement {
114
+ if let to {
115
+ requirement = . range( range. lowerBound..< to)
116
+ } else {
117
+ requirement = . range( range)
118
+ }
86
119
} else {
87
- throw StringError ( " must specify one of --branch, --from-version, or --exact-version " )
120
+ requirement = firstRequirement
121
+
122
+ if to != nil {
123
+ throw StringError ( " --to can only be specified with --from or --up-to-next-minor-from " )
124
+ }
88
125
}
89
126
90
127
// Figure out the location of the package.
91
128
let location : PackageDependency . SourceControl . Location
92
- if let path = try ? Basics . AbsolutePath ( validating: url ) {
129
+ if let path = try ? Basics . AbsolutePath ( validating: dependency ) {
93
130
location = . local( path)
94
131
} else {
95
- location = . remote( . init( url ) )
132
+ location = . remote( . init( dependency ) )
96
133
}
97
134
98
135
let packageDependency : PackageDependency = . sourceControl(
0 commit comments