@@ -45,6 +45,11 @@ public protocol WorkspaceDelegate: class {
4545
4646 /// Called when the resolver is about to be run.
4747 func willResolveDependencies( )
48+
49+ /// Called when the Package.resolved file is changed *outside* of libSwiftPM operations.
50+ ///
51+ /// This is only fired when activated using Workspace's watchResolvedFile() method.
52+ func resolvedFileChanged( )
4853}
4954
5055public extension WorkspaceDelegate {
@@ -53,6 +58,7 @@ public extension WorkspaceDelegate {
5358 func repositoryDidUpdate( _ repository: String ) { }
5459 func willResolveDependencies( ) { }
5560 func dependenciesUpToDate( ) { }
61+ func resolvedFileChanged( ) { }
5662}
5763
5864private class WorkspaceResolverDelegate : DependencyResolverDelegate {
@@ -252,6 +258,9 @@ public class Workspace {
252258 /// The Pins store. The pins file will be created when first pin is added to pins store.
253259 public let pinsStore : LoadableResult < PinsStore >
254260
261+ /// The path to the Package.resolved file for this workspace.
262+ public let resolvedFile : AbsolutePath
263+
255264 /// The path for working repository clones (checkouts).
256265 public let checkoutsPath : AbsolutePath
257266
@@ -291,6 +300,8 @@ public class Workspace {
291300 /// Write dependency resolver trace to a file.
292301 fileprivate let enableResolverTrace : Bool
293302
303+ fileprivate var resolvedFileWatcher : ResolvedFileWatcher ?
304+
294305 /// Typealias for dependency resolver we use in the workspace.
295306 fileprivate typealias PackageDependencyResolver = DependencyResolver
296307 fileprivate typealias PubgrubResolver = PubgrubDependencyResolver
@@ -336,6 +347,7 @@ public class Workspace {
336347 self . enablePubgrubResolver = enablePubgrubResolver
337348 self . skipUpdate = skipUpdate
338349 self . enableResolverTrace = enableResolverTrace
350+ self . resolvedFile = pinsFile
339351
340352 let repositoriesPath = self . dataPath. appending ( component: " repositories " )
341353 self . repositoryManager = RepositoryManager (
@@ -904,13 +916,30 @@ extension Workspace {
904916 }
905917 }
906918 diagnostics. wrap ( { try pinsStore. saveState ( ) } )
919+
920+ // Ask resolved file watcher to update its value so we don't fire
921+ // an extra event if the file was modified by us.
922+ self . resolvedFileWatcher? . updateValue ( )
907923 }
908924}
909925
910926// MARK: - Utility Functions
911927
912928extension Workspace {
913929
930+ /// Watch the Package.resolved for changes.
931+ ///
932+ /// This is useful if clients want to be notified when the Package.resolved
933+ /// file is changed *outside* of libSwiftPM operations. For example, as part
934+ /// of a git operation.
935+ public func watchResolvedFile( ) throws {
936+ // Return if we're already watching it.
937+ guard self . resolvedFileWatcher == nil else { return }
938+ self . resolvedFileWatcher = try ResolvedFileWatcher ( resolvedFile: self . resolvedFile) { [ weak self] in
939+ self ? . delegate? . resolvedFileChanged ( )
940+ }
941+ }
942+
914943 /// Create the cache directories.
915944 fileprivate func createCacheDirectories( with diagnostics: DiagnosticsEngine ) {
916945 do {
0 commit comments