@@ -2757,6 +2757,92 @@ final class WorkspaceTests: XCTestCase {
27572757 }
27582758 }
27592759
2760+ func testStateModified( ) throws {
2761+ let sandbox = AbsolutePath ( " /tmp/ws/ " )
2762+ let fs = InMemoryFileSystem ( )
2763+
2764+ let workspace = try MockWorkspace (
2765+ sandbox: sandbox,
2766+ fileSystem: fs,
2767+ roots: [
2768+ MockPackage (
2769+ name: " Root " ,
2770+ targets: [
2771+ MockTarget ( name: " Root " , dependencies: [
2772+ . product( name: " Foo " , package : " foo " ) ,
2773+ . product( name: " Bar " , package : " bar " )
2774+ ] ) ,
2775+ ] ,
2776+ dependencies: [
2777+ . sourceControl( url: " https://scm.com/org/foo " , requirement: . upToNextMajor( from: " 1.0.0 " ) ) ,
2778+ . sourceControl( url: " https://scm.com/org/bar " , requirement: . upToNextMajor( from: " 1.0.0 " ) ) ,
2779+ ]
2780+ ) ,
2781+ ] ,
2782+ packages: [
2783+ MockPackage (
2784+ name: " Foo " ,
2785+ url: " https://scm.com/org/foo " ,
2786+ targets: [
2787+ MockTarget ( name: " Foo " ) ,
2788+ ] ,
2789+ products: [
2790+ MockProduct ( name: " Foo " , targets: [ " Foo " ] ) ,
2791+ ] ,
2792+ versions: [ nil , " 1.0.0 " , " 1.1.0 " ]
2793+ ) ,
2794+ MockPackage (
2795+ name: " Bar " ,
2796+ url: " https://scm.com/org/bar " ,
2797+ targets: [
2798+ MockTarget ( name: " Bar " ) ,
2799+ ] ,
2800+ products: [
2801+ MockProduct ( name: " Bar " , targets: [ " Bar " ] ) ,
2802+ ] ,
2803+ versions: [ " 1.0.0 " , " 1.1.0 " , " 1.2.0 " ]
2804+ ) ,
2805+ ]
2806+ )
2807+
2808+ try workspace. checkPackageGraph ( roots: [ " Root " ] , deps: [ ] ) { graph, diagnostics in
2809+ XCTAssertNoDiagnostics ( diagnostics)
2810+ PackageGraphTester ( graph) { result in
2811+ result. check ( packages: " Bar " , " Foo " , " Root " )
2812+ }
2813+ }
2814+
2815+ let underlying = try workspace. getOrCreateWorkspace ( )
2816+ let fooEditPath = sandbox. appending ( components: [ " edited " , " foo " ] )
2817+
2818+ // mimic external process putting a dependency into edit mode
2819+ do {
2820+ try fs. createDirectory ( fooEditPath, recursive: true )
2821+ try fs. writeFileContents ( fooEditPath. appending ( component: " Package.swift " ) , bytes: " // swift-tools-version: 5.6 " )
2822+
2823+ let fooState = underlying. state. dependencies [ . plain( " foo " ) ] !
2824+ let externalState = WorkspaceState ( fileSystem: fs, storageDirectory: underlying. state. storagePath. parentDirectory, initializationWarningHandler: { _ in } )
2825+ externalState. dependencies. remove ( fooState. packageRef. identity)
2826+ externalState. dependencies. add ( try fooState. edited ( subpath: . init( " foo " ) , unmanagedPath: fooEditPath) )
2827+ try externalState. save ( )
2828+ }
2829+
2830+ // reload graph after "external" change
2831+ try workspace. checkPackageGraph ( roots: [ " Root " ] , deps: [ ] ) { graph, diagnostics in
2832+ PackageGraphTester ( graph) { result in
2833+ result. check ( packages: " Bar " , " Foo " , " Root " )
2834+ }
2835+ }
2836+
2837+ do {
2838+ let fooState = underlying. state. dependencies [ . plain( " foo " ) ] !
2839+ guard case . edited( basedOn: _, unmanagedPath: fooEditPath) = fooState. state else {
2840+ XCTFail ( " ' \( fooState. packageRef. identity) ' dependency expected to be in edit mode, but was: \( fooState) " )
2841+ return
2842+ }
2843+ }
2844+ }
2845+
27602846 func testSkipUpdate( ) throws {
27612847 let sandbox = AbsolutePath ( " /tmp/ws/ " )
27622848 let fs = InMemoryFileSystem ( )
0 commit comments