rename.fsx:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// -------------------------------------------------------------------------------
// Initial rename of library and project script
// -------------------------------------------------------------------------------
// Bind operator
let (>>=) m f = Option.bind f m
// Args function that parses command line arguments
let getArg argv key =
let arg = Array.tryFind(fun (a:string) -> a.StartsWith(key)) argv
match arg with
| Some x -> x.Replace(key, "") |> Some
| None -> None
// Thread-safe console logger
let ts () = System.DateTime.Now.ToString("o") // ISO-8601
let cw (s:string) = System.Console.WriteLine(s) // Threadsafe console writer
let cew (s:string) = System.Console.Error.WriteLine(s) // Threadsafe console error writer
type LogLevel = Info | Warning | Error
let log level x y =
let msg = sprintf "%s - %A: %A (%A)" (ts()) level x y
match level with
| LogLevel.Error -> cew msg
| LogLevel.Info | LogLevel.Warning -> cw msg
// Generic process executer (needed for "git mv source target")
let executeProcess exe args dir =
try
let psi = new System.Diagnostics.ProcessStartInfo(exe,args)
psi.CreateNoWindow <- true
psi.UseShellExecute <- false
psi.RedirectStandardOutput <- true
psi.RedirectStandardError <- true
psi.WorkingDirectory <- dir
let p = System.Diagnostics.Process.Start(psi)
let o = new System.Text.StringBuilder()
let e = new System.Text.StringBuilder()
p.OutputDataReceived.Add(fun x -> o.AppendLine(x.Data) |> ignore)
p.ErrorDataReceived.Add(fun x -> e.AppendLine(x.Data) |> ignore)
p.BeginErrorReadLine()
p.BeginOutputReadLine()
p.WaitForExit()
(p.ExitCode, o.ToString(), e.ToString()) |> Some
with ex -> log LogLevel.Error (exe,args,dir) ex; None
// Scaffold & Template
let scaffold = "FSharp.ProjectScaffold"
let template = "FSharp.ProjectTemplate"
// The name of the library (will replace "FSharp.ProjectScaffold")
let lib =
((fsi.CommandLineArgs,"lib=") ||> getArg, "FSharp.Foo")
||> defaultArg
// The name of the project (will replace "FSharp.ProjectTemplate")
let proj =
((fsi.CommandLineArgs,"proj=") ||> getArg, "FSharp.Bar")
||> defaultArg
// Folder & file helper functions
let root = __SOURCE_DIRECTORY__
let recursively = System.IO.SearchOption.AllDirectories
let pattern filter = "*" + filter + "*"
let pattern' filter = "*" + filter
let dirs path filter =
System.IO.Directory.EnumerateDirectories(path,filter,recursively)
let files path filter =
System.IO.Directory.EnumerateFiles(path,filter,recursively)
let rev (s:string) =
s |> Seq.toArray |> Array.fold(fun a x -> (x |> string) + a) ""
let replaceFirst input from to' =
let r = new System.Text.RegularExpressions.Regex(from)
r.Replace(input = input,replacement = to', count = 1)
let isGit =
let exe = "git"
let args = sprintf "status"
let git = (exe,args,root) |||> executeProcess
git |> function | Some (x,y,z) -> x = 0 | None -> false
let renameGit path path' =
let exe = "git"
let args = sprintf "mv \"%s\" \"%s\"" path path'
(exe,args,root) |||> executeProcess, path, path'
let renameDirs path path' =
System.IO.Directory.Move(path,path') |> ignore
(0,"","") |> Some,path,path'
let renameFiles path path' =
System.IO.File.Move(path,path') |> ignore
(0,"","") |> Some,path,path'
let rename' path path' =
match isGit with
| true -> (path,path') ||> renameGit
| false ->
match System.IO.File.GetAttributes(path) with
| System.IO.FileAttributes.Directory -> (path,path') ||> renameDirs
| _ -> (path,path') ||> renameFiles
let rename (path:string) from to' =
let from' = from |> rev
let to'' = to' |> rev
let path' = (path |> rev, from', to'') |||> replaceFirst |> rev
(path,path') ||> rename'
let rollback xs = xs |> List.iter(fun (x,y) -> (y,x) ||> rename' |> ignore)
// File content helper functions
let utf8 = System.Text.UTF8Encoding.UTF8
let readLines path = System.IO.File.ReadLines(path,utf8)
let writeLines path (contents:string seq) =
System.IO.File.WriteAllLines(path,contents,utf8)
let copy from to' =
System.IO.File.Copy(from,to',true)
let delete path = System.IO.File.Delete(path)
let extensions = [ ".sln"; ".fs"; ".fsx"; ".fsproj"; ".nuspec"; ".md" ]
// Rename files or directories
let renameIO from to' fn atomic' =
try
(root,from |> pattern) ||> fn
|> Seq.map(fun x -> (x,from,to') |||> rename)
|> Seq.fold(fun (i,acc) (x,y,z) ->
let i' =
match x with
| Some (a,b,c) -> a
| None -> 1
(i+i',(y,z)::acc)) (0,[])
|> fun (x,y) ->
match x with
| 0 -> (y,atomic') ||> List.append |> Some
| _ -> atomic' |> rollback; None
with ex -> log LogLevel.Error (atomic',from,to') ex; None
// Update files content
let updateContent exts atomic' =
try
exts
|> Seq.map(fun x -> (root,x |> pattern') ||> files)
|> Seq.fold(fun a x -> (x,a) ||> Seq.append) Seq.empty
|> Seq.filter(fun x -> not (x.Contains "rename.fsx"))
|> Seq.fold(fun a x ->
let x' = x + "_"
x |> readLines
|> Seq.map(fun y -> y.Replace(scaffold,lib)
.Replace(template,proj))
|> writeLines x'
(x,x')::a) []
|> Seq.iter(fun (x,y) -> (y,x) ||> copy; y |> delete)
|> Some
with ex ->
let git =
match isGit with
| false -> (0,"","") |> Some // Not really rollback but ...
| true ->
let exe = "git"
let args = sprintf "checkout -- *"
(exe,args,root) |||> executeProcess
atomic' |> rollback
log LogLevel.Error (exts,git) ex; None
// Rename with atomicity "git mv file2 file1"
[] |> Some >>= (renameIO scaffold lib dirs)
>>= (renameIO template proj dirs)
>>= (renameIO scaffold lib files)
>>= (renameIO template proj files)
// Update content
>>= (updateContent extensions)
rename.cmd:
@echo off
:: Add the paths for the F# SDK 3.x (from higher version to lower)
set FSHARPSDK=^
C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0\;^
C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0\
cls
:: Execute the script "only" with the first "fsianycpu.exe" found
for %%i in (fsianycpu.exe) do "%%~$FSHARPSDK:i" rename.fsx %*
pause
rename.sh:
#!/bin/bash
#workaround to handle different path for fsi
export FSHARPI=`which fsharpi`
cat - > fsharpi <<"EOF"
#!/bin/bash
$FSHARPI $@
EOF
chmod +x fsharpi
fsharpi rename.fsx $@
rm fsharpi
Git clone FSharp.ProjectScaffold
[ mon@mbai7 rename ] git clone [email protected]:fsprojects/FSharp.ProjectScaffold.git
Cloning into 'FSharp.ProjectScaffold'...
remote: Reusing existing pack: 674, done.
remote: Total 674 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (674/674), 593.40 KiB | 375.00 KiB/s, done.
Resolving deltas: 100% (342/342), done.
Checking connectivity... done.
[ mon@mbai7 rename ] cd FSharp.ProjectScaffold/
Grep for FSharp.ProjectScaffold and FSharp.ProjectTemplate:
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectScaffold" .
./build.fsx:let solutionFile = "FSharp.ProjectScaffold"
./build.fsx:let gitName = "FSharp.ProjectScaffold"
./docs/content/index.fsx: [content]: https://github.com/fsprojects/FSharp.ProjectScaffold/tree/master/docs/content
./docs/content/index.fsx: [gh]: https://github.com/fsprojects/FSharp.ProjectScaffold
./docs/content/index.fsx: [issues]: https://github.com/fsprojects/FSharp.ProjectScaffold/issues
./docs/content/index.fsx: [readme]: https://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/README.md
./docs/content/index.fsx: [license]: https://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/LICENSE.txt
./docs/tools/generate.fsx:let website = "/FSharp.ProjectScaffold"
./docs/tools/generate.fsx:let githubLink = "http://github.com/fsprojects/FSharp.ProjectScaffold"
./docs/tools/generate.fsx: [ "project-name", "FSharp.ProjectScaffold"
./docs/tools/generate.fsx: "project-nuget", "http://nuget.com/packages/FSharp.ProjectScaffold" ]
./nuget/FSharp.ProjectTemplate.nuspec: <licenseUrl>http://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/LICENSE.txt</licenseUrl>
./nuget/FSharp.ProjectTemplate.nuspec: <projectUrl>http://fsprojects.github.com/FSharp.ProjectScaffold</projectUrl>
./nuget/FSharp.ProjectTemplate.nuspec: <iconUrl>https://raw.github.com/fsharp/FSharp.ProjectScaffold/master/nuget/logo.png</iconUrl>
./README.md:FSharp.ProjectScaffold
./README.md: <td><a href="FSharp.ProjectScaffold.sln">FSharp.ProjectScaffold.sln</a></td>
./README.md:<a href="http://fsprojects.github.io/FSharp.ProjectScaffold" target="_blank">Sample API documents available here.</a>
./RELEASE_NOTES.md:* Changed name from fsharp-project-scaffold to FSharp.ProjectScaffold
./rename.fsx:let scaffold = "FSharp.ProjectScaffold"
./rename.fsx:// The name of the library (will replace "FSharp.ProjectScaffold")
./tests/FSharp.ProjectTemplate.Tests/Tests.fs:module FSharp.ProjectScaffold.Tests
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectTemplate" .
./build.fsx:let project = "FSharp.ProjectTemplate"
./docs/content/index.fsx: The F# ProjectTemplate library can be <a href="https://nuget.org/packages/FSharp.ProjectTemplate">installed from NuGet</a>:
./docs/content/index.fsx: <pre>PM> Install-Package FSharp.ProjectTemplate</pre>
./docs/content/index.fsx:#r "FSharp.ProjectTemplate.dll"
./docs/content/index.fsx:open FSharp.ProjectTemplate
./docs/content/tutorial.fsx:#r "FSharp.ProjectTemplate.dll"
./docs/content/tutorial.fsx:open FSharp.ProjectTemplate
./docs/tools/generate.fsx:let referenceBinaries = [ "FSharp.ProjectTemplate.dll" ]
./FSharp.ProjectScaffold.sln:Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.ProjectTemplate", "src\FSharp.ProjectTemplate\FSharp.ProjectTemplate.fsproj", "{7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}"
./FSharp.ProjectScaffold.sln: nuget\FSharp.ProjectTemplate.nuspec = nuget\FSharp.ProjectTemplate.nuspec
./FSharp.ProjectScaffold.sln:Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.ProjectTemplate.Tests", "tests\FSharp.ProjectTemplate.Tests\FSharp.ProjectTemplate.Tests.fsproj", "{E789C72A-5CFD-436B-8EF1-61AA2852A89F}"
./nuget/FSharp.ProjectTemplate.nuspec: <file src="..\bin\FSharp.ProjectTemplate.dll" target="lib/net40" />
./README.md: A good way to get started is to rename the project included in this sample (FSharp.ProjectTemplate).
./rename.fsx:let template = "FSharp.ProjectTemplate"
./rename.fsx:// The name of the project (will replace "FSharp.ProjectTemplate")
./src/FSharp.ProjectTemplate/AssemblyInfo.fs:[<assembly: AssemblyTitleAttribute("FSharp.ProjectTemplate")>]
./src/FSharp.ProjectTemplate/AssemblyInfo.fs:[<assembly: AssemblyProductAttribute("FSharp.ProjectTemplate")>]
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj: <RootNamespace>FSharp.ProjectTemplate</RootNamespace>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj: <AssemblyName>FSharp.ProjectTemplate</AssemblyName>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj: <Name>FSharp.ProjectTemplate</Name>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj: <DocumentationFile>bin\Debug\FSharp.ProjectTemplate.xml</DocumentationFile>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj: <DocumentationFile>..\..\bin\FSharp.ProjectTemplate.xml</DocumentationFile>
./src/FSharp.ProjectTemplate/Library.fs:namespace FSharp.ProjectTemplate
./src/FSharp.ProjectTemplate/Script.fsx:open FSharp.ProjectTemplate
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <RootNamespace>FSharp.ProjectTemplate.Tests</RootNamespace>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <AssemblyName>FSharp.ProjectTemplate.Tests</AssemblyName>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <Name>FSharp.ProjectTemplate.Tests</Name>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <DocumentationFile>bin\Release\FSharp.ProjectTemplate.Tests.xml</DocumentationFile>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <ProjectReference Include="..\..\src\FSharp.ProjectTemplate\FSharp.ProjectTemplate.fsproj">
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj: <Name>FSharp.ProjectTemplate</Name>
./tests/FSharp.ProjectTemplate.Tests/Tests.fs:open FSharp.ProjectTemplate
Rename FSharp.ProjectScaffold and FSharp.ProjectTemplate:
[ mon@mbai7 FSharp.ProjectScaffold ] cp ../rename.* .
‘../rename.cmd’ -> ‘./rename.cmd’
‘../rename.fsx’ -> ‘./rename.fsx’
‘../rename.sh’ -> ‘./rename.sh’
[ mon@mbai7 FSharp.ProjectScaffold ] chmod +x rename.sh
[ mon@mbai7 FSharp.ProjectScaffold ] ./rename.sh lib=Stermon.Foo proj=Stermon.Bar
Grep for FSharp.ProjectScaffold and FSharp.ProjectTemplate (again):
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectScaffold" .
./rename.fsx:let scaffold = "FSharp.ProjectScaffold"
./rename.fsx:// The name of the library (will replace "FSharp.ProjectScaffold")
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectTemplate" .
./rename.fsx:let template = "FSharp.ProjectTemplate"
./rename.fsx:// The name of the project (will replace "FSharp.ProjectTemplate")
Build FSharp.ProjectScaffold:
[ mon@mbai7 FSharp.ProjectScaffold ] chmod +x build.sh
[ mon@mbai7 FSharp.ProjectScaffold ] ./build.sh
Installing 'FAKE 2.15.2'.
Successfully installed 'FAKE 2.15.2'.
fsharpi build.fsx
Building project with version: LocalBuild
Shortened DependencyGraph for Target All:
<== All
<== RunTests
<== Build
<== AssemblyInfo
<== RestorePackages
<== Clean
The resulting target order is:
- Clean
- RestorePackages
- AssemblyInfo
- Build
- RunTests
- All
Starting Target: All (==> RunTests)
Starting Target: RunTests (==> Build)
Starting Target: Build (==> AssemblyInfo)
Starting Target: AssemblyInfo (==> RestorePackages)
Starting Target: RestorePackages (==> Clean)
Starting Target: Clean
Deleting contents of bin
Deleting contents of temp
Finished Target: Clean
...
Execution Runtime: mono-3.5
***** Stermon.Foo.Tests.hello returns 42
42
Tests run: 1, Errors: 0, Failures: 0, Inconclusive: 0, Time: 0.0387905 seconds
Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0
Finished Target: RunTests
Finished Target: All
Killing all processes that are created by FAKE and are still running.
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:00.0043722
RestorePackages 00:00:02.4633336
AssemblyInfo 00:00:00.0062624
Build 00:00:05.3281672
RunTests 00:00:01.1349369
All 00:00:00.0000441
Total: 00:00:08.9734871
Status: Ok
---------------------------------------------------------------------
Stermon.Foo and Stermon.Bar:
[ mon@mbai7 FSharp.ProjectScaffold ] ll . bin/ src/ tests/
.:
total 64K
-rw-r--r-- 1 mon staff 1.2K Apr 25 18:20 LICENSE.txt
-rw-r--r-- 1 mon staff 16K Apr 25 18:45 README.md
-rw-r--r-- 1 mon staff 374 Apr 25 18:45 RELEASE_NOTES.md
-rw-r--r-- 1 mon staff 3.2K Apr 25 18:45 Stermon.Foo.sln
-rw-r--r-- 1 mon staff 1.7K Apr 25 18:48 TestResults.xml
drwxr-xr-x 5 mon staff 170 Apr 25 18:48 bin/
-rw-r--r-- 1 mon staff 182 Apr 25 18:20 build.cmd
-rw-r--r-- 1 mon staff 5.6K Apr 25 18:45 build.fsx
-rwxr-xr-x 1 mon staff 398 Apr 25 18:20 build.sh*
drwxr-xr-x 6 mon staff 204 Apr 25 18:20 docs/
drwxr-xr-x 3 mon staff 102 Apr 25 18:45 lib/
drwxr-xr-x 5 mon staff 170 Apr 25 18:45 nuget/
drwxr-xr-x 10 mon staff 340 Apr 25 18:48 packages/
-rw-r--r-- 1 mon staff 39 Apr 25 18:44 rename.cmd
-rw-r--r-- 1 mon staff 5.2K Apr 25 18:44 rename.fsx
-rwxr-xr-x 1 mon staff 59 Apr 25 18:44 rename.sh*
drwxr-xr-x 3 mon staff 102 Apr 25 18:41 src/
drwxr-xr-x 2 mon staff 68 Apr 25 18:48 temp/
drwxr-xr-x 3 mon staff 102 Apr 25 18:41 tests/
bin/:
total 12K
-rwxr-xr-x 1 mon staff 4.0K Apr 25 18:48 Stermon.Bar.dll*
-rw-r--r-- 1 mon staff 276 Apr 25 18:48 Stermon.Bar.dll.mdb
-rw-r--r-- 1 mon staff 196 Apr 25 18:48 Stermon.Bar.xml
src/:
total 0
drwxr-xr-x 7 mon staff 238 Apr 25 18:48 Stermon.Bar/
tests/:
total 0
drwxr-xr-x 7 mon staff 238 Apr 25 18:48 Stermon.Bar.Tests/
Git status:
[ mon@mbai7 FSharp.ProjectScaffold ] git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: FSharp.ProjectScaffold.sln -> Stermon.Foo.sln
renamed: nuget/FSharp.ProjectTemplate.nuspec -> nuget/Stermon.Bar.nuspec
renamed: src/FSharp.ProjectTemplate/AssemblyInfo.fs -> src/Stermon.Bar/AssemblyInfo.fs
renamed: src/FSharp.ProjectTemplate/Library.fs -> src/Stermon.Bar/Library.fs
renamed: src/FSharp.ProjectTemplate/Script.fsx -> src/Stermon.Bar/Script.fsx
renamed: src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj -> src/Stermon.Bar/Stermon.Bar.fsproj
renamed: tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj -> tests/Stermon.Bar.Tests/Stermon.Bar.Tests.fsproj
renamed: tests/FSharp.ProjectTemplate.Tests/Tests.fs -> tests/Stermon.Bar.Tests/Tests.fs
renamed: tests/FSharp.ProjectTemplate.Tests/packages.config -> tests/Stermon.Bar.Tests/packages.config
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: RELEASE_NOTES.md
modified: Stermon.Foo.sln
deleted: bin/README.md
modified: build.fsx
modified: build.sh
modified: docs/content/index.fsx
modified: docs/content/tutorial.fsx
modified: docs/output/README.md
modified: docs/tools/generate.fsx
modified: lib/README.md
modified: nuget/README.md
modified: nuget/Stermon.Bar.nuspec
modified: packages/README.md
modified: src/Stermon.Bar/AssemblyInfo.fs
modified: src/Stermon.Bar/Library.fs
modified: src/Stermon.Bar/Script.fsx
modified: src/Stermon.Bar/Stermon.Bar.fsproj
deleted: temp/README.md
modified: tests/Stermon.Bar.Tests/Stermon.Bar.Tests.fsproj
modified: tests/Stermon.Bar.Tests/Tests.fs
Untracked files:
(use "git add <file>..." to include in what will be committed)
rename.cmd
rename.fsx
rename.sh
References:
- fsprojects: FSharp.ProjectScaffold