1
1
namespace EntityFrameworkCore.FSharp.Migrations.Design
2
2
3
+ open System
4
+ open System.IO
5
+ open System.Text
3
6
open Microsoft.EntityFrameworkCore .Migrations .Design
4
7
open Microsoft.EntityFrameworkCore .Internal
5
8
open EntityFrameworkCore.FSharp .IndentedStringBuilderUtilities
6
- open System.Text
7
- open System.IO
9
+ open System
10
+ open System
11
+ open Microsoft.EntityFrameworkCore
12
+
8
13
9
14
type FSharpMigrationsScaffolder ( dependencies ) =
10
15
inherit MigrationsScaffolder( dependencies)
@@ -46,8 +51,86 @@ type FSharpMigrationsScaffolder(dependencies) =
46
51
Directory.CreateDirectory( modelSnapshotDirectory) |> ignore
47
52
File.WriteAllText( modelSnapshotFile, migration.SnapshotCode, Encoding.UTF8)
48
53
54
+ let projectFiles =
55
+ Directory.GetFiles( projectDir)
56
+ |> Seq.filter ( fun f -> f.EndsWith " .fsproj" )
57
+ |> Seq.toList
58
+
59
+ match projectFiles with
60
+ | [] -> dependencies.OperationReporter.WriteVerbose( sprintf " Unable to find .fsproj file in %s " projectDir)
61
+
62
+ | [ projectFile ] ->
63
+ let projectDirectory = Path.GetDirectoryName projectFile
64
+ let projectContents = File.ReadAllLines projectFile
65
+
66
+ let allDbContextTypes =
67
+ dependencies.MigrationsAssembly.Assembly.GetTypes()
68
+ |> Seq.filter ( fun t -> typeof< DbContext>. IsAssignableFrom t)
69
+ |> Seq.map ( fun t -> sprintf " type %s " t.Name)
70
+
71
+ let declaringFiles =
72
+ projectContents
73
+ |> Seq.filter ( fun l -> l.Contains( " <Compile Include=\" " ))
74
+ |> Seq.map ( fun l -> l.Replace( " <Compile Include=\" " , " " ) .Replace( " />" , " " ) .TrimStart() .TrimEnd() .TrimEnd( '"' ))
75
+ |> Seq.map ( fun l -> ( l, File.ReadAllText l))
76
+ |> Seq.filter ( fun ( _ , c ) -> allDbContextTypes |> Seq.exists ( fun t -> c.Contains t))
77
+ |> Seq.map fst
78
+ |> Seq.toList
79
+
80
+ let rec calculateInsertPoint ( compileIncludesToFind : string list ) ( searchLines : ( int * string ) seq ) ( acc : int ) =
81
+ match compileIncludesToFind with
82
+ | [ ] -> acc + 1
83
+ | _ ->
84
+ let line = compileIncludesToFind.Head
85
+ let location =
86
+ searchLines
87
+ |> Seq.skipWhile ( fun ( _ , l ) -> l.Contains( sprintf " \" %s \" " line) |> not )
88
+ |> Seq.map fst
89
+ |> Seq.head
90
+
91
+ let newLocation = if location > acc then location else acc
92
+ calculateInsertPoint ( compileIncludesToFind.Tail) searchLines newLocation
93
+
94
+ let indexedProjectContents =
95
+ projectContents
96
+ |> Seq.mapi ( fun i l -> ( i, l))
97
+
98
+ let insertionPoint =
99
+ calculateInsertPoint declaringFiles indexedProjectContents 0
100
+
101
+ let indentation =
102
+ ( projectContents
103
+ |> Seq.toArray).[ insertionPoint + 1 ]
104
+ |> Seq.takeWhile ( fun c -> c = ' ' )
105
+ |> String.Concat
106
+
107
+ let compileIncludes =
108
+ [ migrationFile; modelSnapshotFile; if migration.MigrationCode <> " // intentionally empty" then migrationMetadataFile; ]
109
+ |> Seq.filter ( isNull >> not )
110
+ |> Seq.map ( fun s -> s.Replace( projectDirectory, " " ) .TrimStart( '\\' ))
111
+ |> Seq.map ( fun s -> sprintf " %s <Compile Include=\" %s \" />" indentation s)
112
+ |> Seq.toList
113
+
114
+ let startProjectFile =
115
+ projectContents
116
+ |> Seq.take insertionPoint
117
+ |> Seq.toList
118
+
119
+ let endProjectFile =
120
+ projectContents
121
+ |> Seq.skip insertionPoint
122
+ |> Seq.toList
123
+
124
+ let newProjectContents =
125
+ [ startProjectFile; compileIncludes; endProjectFile ]
126
+ |> List.concat
127
+
128
+ File.WriteAllLines( projectFile, newProjectContents)
129
+
130
+ | _ -> dependencies.OperationReporter.WriteVerbose( sprintf " Ambiguous .fsproj file in %s . Please manually add the generated files." projectDir)
131
+
49
132
MigrationFiles (
50
133
MigrationFile = migrationFile,
51
134
MetadataFile = migrationMetadataFile,
52
135
SnapshotFile = modelSnapshotFile
53
- )
136
+ )
0 commit comments