blob: 999c85977655c12773a971f744ad97edc5fd3f14 [file] [log] [blame]
mistachkin7aa3ebe2016-02-24 21:42:03 +00001#!/usr/bin/tclsh
2#
3# This script is used to quickly test a VSIX (Visual Studio Extension) file
4# with Visual Studio 2015 on Windows.
5#
6# PREREQUISITES
7#
mistachkin6ae4d842016-02-25 02:56:53 +00008# 1. This tool must be executed with "elevated administrator" privileges.
mistachkin7aa3ebe2016-02-24 21:42:03 +00009#
mistachkin6ae4d842016-02-25 02:56:53 +000010# 2. Tcl 8.4 and later are supported, earlier versions have not been tested.
11#
12# 3. The "sqlite-UWP-output.vsix" file is assumed to exist in the parent
mistachkin7aa3ebe2016-02-24 21:42:03 +000013# directory of the directory containing this script. The [optional] first
14# command line argument to this script may be used to specify an alternate
15# file. However, currently, the file must be compatible with both Visual
16# Studio 2015 and the Universal Windows Platform.
17#
mistachkin6ae4d842016-02-25 02:56:53 +000018# 4. The "VERSION" file is assumed to exist in the parent directory of the
mistachkinc32db462016-02-25 02:49:58 +000019# directory containing this script. It must contain a version number that
20# matches the VSIX file being tested.
21#
mistachkin6ae4d842016-02-25 02:56:53 +000022# 5. The temporary directory specified in the TEMP or TMP environment variables
mistachkin7aa3ebe2016-02-24 21:42:03 +000023# must refer to an existing directory writable by the current user.
24#
mistachkin6ae4d842016-02-25 02:56:53 +000025# 6. The VS140COMNTOOLS environment variable must refer to the Visual Studio
mistachkin7aa3ebe2016-02-24 21:42:03 +000026# 2015 common tools directory.
27#
28# USAGE
29#
30# The first argument to this script is optional. If specified, it must be the
31# name of the VSIX file to test.
32#
33package require Tcl 8.4
34
35proc fail { {error ""} {usage false} } {
36 if {[string length $error] > 0} then {
37 puts stdout $error
38 if {!$usage} then {exit 1}
39 }
40
41 puts stdout "usage:\
42[file tail [info nameofexecutable]]\
43[file tail [info script]] \[vsixFile\]"
44
45 exit 1
46}
47
48proc getEnvironmentVariable { name } {
49 #
50 # NOTE: Returns the value of the specified environment variable or an empty
51 # string for environment variables that do not exist in the current
52 # process environment.
53 #
54 return [expr {[info exists ::env($name)] ? $::env($name) : ""}]
55}
56
57proc getTemporaryPath {} {
58 #
59 # NOTE: Returns the normalized path to the first temporary directory found
60 # in the typical set of environment variables used for that purpose
61 # or an empty string to signal a failure to locate such a directory.
62 #
63 set names [list]
64
65 foreach name [list TEMP TMP] {
66 lappend names [string toupper $name] [string tolower $name] \
67 [string totitle $name]
68 }
69
70 foreach name $names {
71 set value [getEnvironmentVariable $name]
72
73 if {[string length $value] > 0} then {
74 return [file normalize $value]
75 }
76 }
77
78 return ""
79}
80
81proc appendArgs { args } {
82 #
mistachkin77b7e2a2016-02-25 08:02:16 +000083 # NOTE: Returns all passed arguments joined together as a single string
84 # with no intervening spaces between arguments.
mistachkin7aa3ebe2016-02-24 21:42:03 +000085 #
86 eval append result $args
87}
88
mistachkinc32db462016-02-25 02:49:58 +000089proc readFile { fileName } {
90 #
91 # NOTE: Reads and returns the entire contents of the specified file, which
92 # may contain binary data.
93 #
94 set file_id [open $fileName RDONLY]
95 fconfigure $file_id -encoding binary -translation binary
96 set result [read $file_id]
97 close $file_id
98 return $result
99}
100
101proc writeFile { fileName data } {
102 #
103 # NOTE: Writes the entire contents of the specified file, which may contain
104 # binary data.
105 #
106 set file_id [open $fileName {WRONLY CREAT TRUNC}]
107 fconfigure $file_id -encoding binary -translation binary
108 puts -nonewline $file_id $data
109 close $file_id
110 return ""
111}
112
113proc putsAndEval { command } {
mistachkin77b7e2a2016-02-25 08:02:16 +0000114 #
115 # NOTE: Outputs a command to the standard output channel and then evaluates
116 # it in the callers context.
117 #
118 catch {
119 puts stdout [appendArgs "Running: " [lrange $command 1 end] ...\n]
120 }
121
mistachkinc32db462016-02-25 02:49:58 +0000122 return [uplevel 1 $command]
123}
124
mistachkin77b7e2a2016-02-25 08:02:16 +0000125proc isBadDirectory { directory } {
126 #
127 # NOTE: Returns non-zero if the directory is empty, does not exist, -OR- is
128 # not a directory.
129 #
130 catch {
131 puts stdout [appendArgs "Checking directory \"" $directory \"...\n]
132 }
133
134 return [expr {[string length $directory] == 0 || \
135 ![file exists $directory] || ![file isdirectory $directory]}]
136}
137
138proc isBadFile { fileName } {
139 #
140 # NOTE: Returns non-zero if the file name is empty, does not exist, -OR- is
141 # not a regular file.
142 #
143 catch {
144 puts stdout [appendArgs "Checking file \"" $fileName \"...\n]
145 }
146
147 return [expr {[string length $fileName] == 0 || \
148 ![file exists $fileName] || ![file isfile $fileName]}]
149}
150
mistachkin7aa3ebe2016-02-24 21:42:03 +0000151#
152# NOTE: This is the entry point for this script.
153#
154set script [file normalize [info script]]
155
156if {[string length $script] == 0} then {
157 fail "script file currently being evaluated is unknown" true
158}
159
mistachkin77b7e2a2016-02-25 08:02:16 +0000160set path [file normalize [file dirname $script]]
161set argc [llength $argv]; if {$argc > 1} then {fail "" true}
mistachkin7aa3ebe2016-02-24 21:42:03 +0000162
163if {$argc == 1} then {
mistachkinc32db462016-02-25 02:49:58 +0000164 set vsixFileName [lindex $argv 0]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000165} else {
mistachkin77b7e2a2016-02-25 08:02:16 +0000166 set vsixFileName [file join \
167 [file dirname $path] sqlite-UWP-output.vsix]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000168}
169
mistachkin77b7e2a2016-02-25 08:02:16 +0000170###############################################################################
mistachkin7aa3ebe2016-02-24 21:42:03 +0000171
mistachkin77b7e2a2016-02-25 08:02:16 +0000172if {[isBadFile $vsixFileName]} then {
173 fail [appendArgs \
174 "VSIX file \"" $vsixFileName "\" does not exist"]
mistachkinc32db462016-02-25 02:49:58 +0000175}
176
177set versionFileName [file join [file dirname $path] VERSION]
178
mistachkin77b7e2a2016-02-25 08:02:16 +0000179if {[isBadFile $versionFileName]} then {
180 fail [appendArgs \
181 "Version file \"" $versionFileName "\" does not exist"]
mistachkinc32db462016-02-25 02:49:58 +0000182}
183
184set projectTemplateFileName [file join $path vsixtest.vcxproj.data]
mistachkinc32db462016-02-25 02:49:58 +0000185
mistachkin77b7e2a2016-02-25 08:02:16 +0000186if {[isBadFile $projectTemplateFileName]} then {
mistachkinc32db462016-02-25 02:49:58 +0000187 fail [appendArgs \
mistachkin77b7e2a2016-02-25 08:02:16 +0000188 "Project template file \"" $projectTemplateFileName \
189 "\" does not exist"]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000190}
191
192set envVarName VS140COMNTOOLS
193set vsDirectory [getEnvironmentVariable $envVarName]
194
mistachkin77b7e2a2016-02-25 08:02:16 +0000195if {[isBadDirectory $vsDirectory]} then {
mistachkin7aa3ebe2016-02-24 21:42:03 +0000196 fail [appendArgs \
197 "Visual Studio 2015 directory \"" $vsDirectory \
mistachkin77b7e2a2016-02-25 08:02:16 +0000198 "\" from environment variable \"" $envVarName \
mistachkin7aa3ebe2016-02-24 21:42:03 +0000199 "\" does not exist"]
200}
201
mistachkin77b7e2a2016-02-25 08:02:16 +0000202set vsixInstaller [file join \
203 [file dirname $vsDirectory] IDE VSIXInstaller.exe]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000204
mistachkin77b7e2a2016-02-25 08:02:16 +0000205if {[isBadFile $vsixInstaller]} then {
mistachkin7aa3ebe2016-02-24 21:42:03 +0000206 fail [appendArgs \
207 "Visual Studio 2015 VSIX installer \"" $vsixInstaller \
208 "\" does not exist"]
209}
210
211set envVarName ProgramFiles
212set programFiles [getEnvironmentVariable $envVarName]
213
mistachkin77b7e2a2016-02-25 08:02:16 +0000214if {[isBadDirectory $programFiles]} then {
mistachkin7aa3ebe2016-02-24 21:42:03 +0000215 fail [appendArgs \
mistachkin77b7e2a2016-02-25 08:02:16 +0000216 "Program Files directory \"" $programFiles \
217 "\" from environment variable \"" $envVarName \
218 "\" does not exist"]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000219}
220
221set msBuild [file join $programFiles MSBuild 14.0 Bin MSBuild.exe]
222
mistachkin77b7e2a2016-02-25 08:02:16 +0000223if {[isBadFile $msBuild]} then {
mistachkin7aa3ebe2016-02-24 21:42:03 +0000224 fail [appendArgs \
mistachkin77b7e2a2016-02-25 08:02:16 +0000225 "MSBuild v14.0 executable file \"" $msBuild \
226 "\" does not exist"]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000227}
228
229set temporaryDirectory [getTemporaryPath]
230
mistachkin77b7e2a2016-02-25 08:02:16 +0000231if {[isBadDirectory $temporaryDirectory]} then {
232 fail [appendArgs \
233 "Temporary directory \"" $temporaryDirectory \
234 "\" does not exist"]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000235}
236
mistachkin77b7e2a2016-02-25 08:02:16 +0000237###############################################################################
238
mistachkin7aa3ebe2016-02-24 21:42:03 +0000239set installLogFileName [appendArgs \
mistachkin77b7e2a2016-02-25 08:02:16 +0000240 [file rootname [file tail $vsixFileName]] \
241 -install- [pid] .log]
242
243set commands(1) [list exec [file nativename $vsixInstaller]]
244
245lappend commands(1) /quiet /norepair
246lappend commands(1) [appendArgs /logFile: $installLogFileName]
247lappend commands(1) [file nativename $vsixFileName]
248
249###############################################################################
mistachkin7aa3ebe2016-02-24 21:42:03 +0000250
251set buildLogFileName [appendArgs \
mistachkinc32db462016-02-25 02:49:58 +0000252 [file rootname [file tail $vsixFileName]] \
mistachkin78007b22016-02-24 23:25:23 +0000253 -build-%configuration%-%platform%- [pid] .log]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000254
mistachkin78007b22016-02-24 23:25:23 +0000255set commands(2) [list exec [file nativename $msBuild]]
mistachkin77b7e2a2016-02-25 08:02:16 +0000256
mistachkin78007b22016-02-24 23:25:23 +0000257lappend commands(2) [file nativename [file join $path vsixtest.sln]]
258lappend commands(2) /target:Rebuild
259lappend commands(2) /property:Configuration=%configuration%
mistachkin5dad68d2016-02-24 23:31:14 +0000260lappend commands(2) /property:Platform=%platform%
mistachkin7aa3ebe2016-02-24 21:42:03 +0000261
mistachkin78007b22016-02-24 23:25:23 +0000262lappend commands(2) [appendArgs \
mistachkin7aa3ebe2016-02-24 21:42:03 +0000263 /logger:FileLogger,Microsoft.Build.Engine\;Logfile= \
mistachkin77b7e2a2016-02-25 08:02:16 +0000264 [file nativename [file join $temporaryDirectory \
265 $buildLogFileName]] \;Verbosity=diagnostic]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000266
mistachkin77b7e2a2016-02-25 08:02:16 +0000267###############################################################################
268
269set uninstallLogFileName [appendArgs \
270 [file rootname [file tail $vsixFileName]] \
271 -uninstall- [pid] .log]
272
273set commands(3) [list exec [file nativename $vsixInstaller]]
274
275lappend commands(3) /quiet /norepair
mistachkin78007b22016-02-24 23:25:23 +0000276lappend commands(3) [appendArgs /logFile: $uninstallLogFileName]
277lappend commands(3) [appendArgs /uninstall:SQLite.UWP.2015]
mistachkin7aa3ebe2016-02-24 21:42:03 +0000278
mistachkinc32db462016-02-25 02:49:58 +0000279###############################################################################
mistachkin7aa3ebe2016-02-24 21:42:03 +0000280
mistachkin5dad68d2016-02-24 23:31:14 +0000281if {1} then {
mistachkin77b7e2a2016-02-25 08:02:16 +0000282 catch {
283 puts stdout [appendArgs \
284 "Install log: \"" [file nativename [file join \
285 $temporaryDirectory $installLogFileName]] \"\n]
286 }
mistachkin78007b22016-02-24 23:25:23 +0000287
mistachkin77b7e2a2016-02-25 08:02:16 +0000288 catch {
289 puts stdout [appendArgs \
290 "Build logs: \"" [file nativename [file join \
291 $temporaryDirectory $buildLogFileName]] \"\n]
292 }
mistachkinc32db462016-02-25 02:49:58 +0000293
mistachkin77b7e2a2016-02-25 08:02:16 +0000294 catch {
295 puts stdout [appendArgs \
296 "Uninstall log: \"" [file nativename [file join \
297 $temporaryDirectory $uninstallLogFileName]] \"\n]
298 }
mistachkinc32db462016-02-25 02:49:58 +0000299}
300
301###############################################################################
302
303if {1} then {
mistachkin6ae4d842016-02-25 02:56:53 +0000304 putsAndEval $commands(1)
mistachkinc32db462016-02-25 02:49:58 +0000305
306 set versionNumber [string trim [readFile $versionFileName]]
307 set data [readFile $projectTemplateFileName]
308 set data [string map [list %versionNumber% $versionNumber] $data]
mistachkin77b7e2a2016-02-25 08:02:16 +0000309
310 set projectFileName [file join $path vsixtest.vcxproj]
mistachkinc32db462016-02-25 02:49:58 +0000311 writeFile $projectFileName $data
312
313 set platforms [list x86 x64 ARM]
mistachkin78007b22016-02-24 23:25:23 +0000314 set configurations [list Debug Release]
315
316 foreach platform $platforms {
317 foreach configuration $configurations {
mistachkinc32db462016-02-25 02:49:58 +0000318 putsAndEval [string map [list \
mistachkin77b7e2a2016-02-25 08:02:16 +0000319 %platform% $platform %configuration% $configuration] \
320 $commands(2)]
mistachkin78007b22016-02-24 23:25:23 +0000321 }
322 }
323
mistachkin6ae4d842016-02-25 02:56:53 +0000324 putsAndEval $commands(3)
mistachkin78007b22016-02-24 23:25:23 +0000325}