1
1
/*
2
2
This source file is part of the Swift.org open source project
3
3
4
- Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
4
+ Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
5
5
Licensed under Apache License v2.0 with Runtime Library Exception
6
6
7
7
See http://swift.org/LICENSE.txt for license information
@@ -251,16 +251,28 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
251
251
252
252
// A wrapper for getDependencies() errors. This adds additional information
253
253
// about the container to identify it for diagnostics.
254
- public struct GetDependenciesErrorWrapper : Swift . Error {
254
+ public struct GetDependenciesError : Error , CustomStringConvertible {
255
255
256
- /// The container which had this error.
256
+ /// The container (repository) that encountered the error.
257
257
public let containerIdentifier : String
258
258
259
- /// The source control reference i.e. version, branch, revsion etc.
259
+ /// The source control reference ( version, branch, revision, etc) that was involved .
260
260
public let reference : String
261
261
262
262
/// The actual error that occurred.
263
- public let underlyingError : Swift . Error
263
+ public let underlyingError : Error
264
+
265
+ /// Optional suggestion for how to resolve the error.
266
+ public let suggestion : String ?
267
+
268
+ /// Description shown for errors of this kind.
269
+ public var description : String {
270
+ var desc = " \( underlyingError) in \( containerIdentifier) "
271
+ if let suggestion = suggestion {
272
+ desc += " ( \( suggestion) ) "
273
+ }
274
+ return desc
275
+ }
264
276
}
265
277
266
278
/// This is used to remember if tools version of a particular version is
@@ -370,8 +382,8 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
370
382
return try getDependencies ( at: revision, version: version, productFilter: productFilter)
371
383
} . 1
372
384
} catch {
373
- throw GetDependenciesErrorWrapper (
374
- containerIdentifier: identifier. repository. url, reference: version. description, underlyingError: error)
385
+ throw GetDependenciesError (
386
+ containerIdentifier: identifier. repository. url, reference: version. description, underlyingError: error, suggestion : nil )
375
387
}
376
388
}
377
389
@@ -383,8 +395,28 @@ public class RepositoryPackageContainer: BasePackageContainer, CustomStringConve
383
395
return try getDependencies ( at: revision, productFilter: productFilter)
384
396
} . 1
385
397
} catch {
386
- throw GetDependenciesErrorWrapper (
387
- containerIdentifier: identifier. repository. url, reference: revision, underlyingError: error)
398
+ // Examine the error to see if we can come up with a more informative and actionable error message. We know that the revision is expected to be a branch name or a hash (tags are handled through a different code path).
399
+ if let gitInvocationError = error as? ProcessResult . Error , gitInvocationError. description. contains ( " Needed a single revision " ) {
400
+ // It was a Git process invocation error. Take a look at the repository to see if we can come up with a reasonable diagnostic.
401
+ if let rev = try ? repository. resolveRevision ( identifier: revision) , repository. exists ( revision: rev) {
402
+ // Revision does exist, so something else must be wrong.
403
+ throw GetDependenciesError (
404
+ containerIdentifier: identifier. repository. url, reference: revision, underlyingError: error, suggestion: nil )
405
+ }
406
+ else {
407
+ // Revision does not exist, so we customize the error.
408
+ let sha1RegEx = try ! RegEx ( pattern: #"\A[:xdigit:]{40}\Z"# )
409
+ let isBranchRev = sha1RegEx. matchGroups ( in: revision) . compactMap { $0 } . isEmpty
410
+ let errorMessage = " could not find " + ( isBranchRev ? " a branch named ‘ \( revision) ’ " : " the commit \( revision) " )
411
+ let mainBranchExists = ( try ? repository. resolveRevision ( identifier: " main " ) ) != nil
412
+ let suggestion = ( revision == " master " && mainBranchExists) ? " did you mean ‘main’? " : nil
413
+ throw GetDependenciesError (
414
+ containerIdentifier: identifier. repository. url, reference: revision,
415
+ underlyingError: StringError ( errorMessage) , suggestion: suggestion)
416
+ }
417
+ }
418
+ // If we get this far without having thrown an error, we wrap and throw the underlying error.
419
+ throw GetDependenciesError ( containerIdentifier: identifier. repository. url, reference: revision, underlyingError: error, suggestion: nil )
388
420
}
389
421
}
390
422
0 commit comments