unity-devkit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1887 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) .NET Foundation and contributors. All rights reserved.
3
+ # Licensed under the MIT license. See LICENSE file in the project root for full license information.
4
+ #
5
+
6
+ # Stop script on NZEC
7
+ set -e
8
+ # Stop script if unbound variable found (use ${var:-} if intentional)
9
+ set -u
10
+ # By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success
11
+ # This is causing it to fail
12
+ set -o pipefail
13
+
14
+ # Use in the the functions: eval $invocation
15
+ invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"'
16
+
17
+ # standard output may be used as a return value in the functions
18
+ # we need a way to write text on the screen in the functions so that
19
+ # it won't interfere with the return value.
20
+ # Exposing stream 3 as a pipe to standard output of the script itself
21
+ exec 3>&1
22
+
23
+ # Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors.
24
+ # See if stdout is a terminal
25
+ if [ -t 1 ] && command -v tput > /dev/null; then
26
+ # see if it supports colors
27
+ ncolors=$(tput colors || echo 0)
28
+ if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
29
+ bold="$(tput bold || echo)"
30
+ normal="$(tput sgr0 || echo)"
31
+ black="$(tput setaf 0 || echo)"
32
+ red="$(tput setaf 1 || echo)"
33
+ green="$(tput setaf 2 || echo)"
34
+ yellow="$(tput setaf 3 || echo)"
35
+ blue="$(tput setaf 4 || echo)"
36
+ magenta="$(tput setaf 5 || echo)"
37
+ cyan="$(tput setaf 6 || echo)"
38
+ white="$(tput setaf 7 || echo)"
39
+ fi
40
+ fi
41
+
42
+ say_warning() {
43
+ printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}" >&3
44
+ }
45
+
46
+ say_err() {
47
+ printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2
48
+ }
49
+
50
+ say() {
51
+ # using stream 3 (defined in the beginning) to not interfere with stdout of functions
52
+ # which may be used as return value
53
+ printf "%b\n" "${cyan:-}dotnet-install:${normal:-} $1" >&3
54
+ }
55
+
56
+ say_verbose() {
57
+ if [ "$verbose" = true ]; then
58
+ say "$1"
59
+ fi
60
+ }
61
+
62
+ # This platform list is finite - if the SDK/Runtime has supported Linux distribution-specific assets,
63
+ # then and only then should the Linux distribution appear in this list.
64
+ # Adding a Linux distribution to this list does not imply distribution-specific support.
65
+ get_legacy_os_name_from_platform() {
66
+ eval $invocation
67
+
68
+ platform="$1"
69
+ case "$platform" in
70
+ "centos.7")
71
+ echo "centos"
72
+ return 0
73
+ ;;
74
+ "debian.8")
75
+ echo "debian"
76
+ return 0
77
+ ;;
78
+ "debian.9")
79
+ echo "debian.9"
80
+ return 0
81
+ ;;
82
+ "fedora.23")
83
+ echo "fedora.23"
84
+ return 0
85
+ ;;
86
+ "fedora.24")
87
+ echo "fedora.24"
88
+ return 0
89
+ ;;
90
+ "fedora.27")
91
+ echo "fedora.27"
92
+ return 0
93
+ ;;
94
+ "fedora.28")
95
+ echo "fedora.28"
96
+ return 0
97
+ ;;
98
+ "opensuse.13.2")
99
+ echo "opensuse.13.2"
100
+ return 0
101
+ ;;
102
+ "opensuse.42.1")
103
+ echo "opensuse.42.1"
104
+ return 0
105
+ ;;
106
+ "opensuse.42.3")
107
+ echo "opensuse.42.3"
108
+ return 0
109
+ ;;
110
+ "rhel.7"*)
111
+ echo "rhel"
112
+ return 0
113
+ ;;
114
+ "ubuntu.14.04")
115
+ echo "ubuntu"
116
+ return 0
117
+ ;;
118
+ "ubuntu.16.04")
119
+ echo "ubuntu.16.04"
120
+ return 0
121
+ ;;
122
+ "ubuntu.16.10")
123
+ echo "ubuntu.16.10"
124
+ return 0
125
+ ;;
126
+ "ubuntu.18.04")
127
+ echo "ubuntu.18.04"
128
+ return 0
129
+ ;;
130
+ "alpine.3.4.3")
131
+ echo "alpine"
132
+ return 0
133
+ ;;
134
+ esac
135
+ return 1
136
+ }
137
+
138
+ get_legacy_os_name() {
139
+ eval $invocation
140
+
141
+ local uname=$(uname)
142
+ if [ "$uname" = "Darwin" ]; then
143
+ echo "osx"
144
+ return 0
145
+ elif [ -n "$runtime_id" ]; then
146
+ echo $(get_legacy_os_name_from_platform "${runtime_id%-*}" || echo "${runtime_id%-*}")
147
+ return 0
148
+ else
149
+ if [ -e /etc/os-release ]; then
150
+ . /etc/os-release
151
+ os=$(get_legacy_os_name_from_platform "$ID${VERSION_ID:+.${VERSION_ID}}" || echo "")
152
+ if [ -n "$os" ]; then
153
+ echo "$os"
154
+ return 0
155
+ fi
156
+ fi
157
+ fi
158
+
159
+ say_verbose "Distribution specific OS name and version could not be detected: UName = $uname"
160
+ return 1
161
+ }
162
+
163
+ get_linux_platform_name() {
164
+ eval $invocation
165
+
166
+ if [ -n "$runtime_id" ]; then
167
+ echo "${runtime_id%-*}"
168
+ return 0
169
+ else
170
+ if [ -e /etc/os-release ]; then
171
+ . /etc/os-release
172
+ echo "$ID${VERSION_ID:+.${VERSION_ID}}"
173
+ return 0
174
+ elif [ -e /etc/redhat-release ]; then
175
+ local redhatRelease=$(</etc/redhat-release)
176
+ if [[ $redhatRelease == "CentOS release 6."* || $redhatRelease == "Red Hat Enterprise Linux "*" release 6."* ]]; then
177
+ echo "rhel.6"
178
+ return 0
179
+ fi
180
+ fi
181
+ fi
182
+
183
+ say_verbose "Linux specific platform name and version could not be detected: UName = $uname"
184
+ return 1
185
+ }
186
+
187
+ is_musl_based_distro() {
188
+ (ldd --version 2>&1 || true) | grep -q musl
189
+ }
190
+
191
+ get_current_os_name() {
192
+ eval $invocation
193
+
194
+ local uname=$(uname)
195
+ if [ "$uname" = "Darwin" ]; then
196
+ echo "osx"
197
+ return 0
198
+ elif [ "$uname" = "FreeBSD" ]; then
199
+ echo "freebsd"
200
+ return 0
201
+ elif [ "$uname" = "Linux" ]; then
202
+ local linux_platform_name=""
203
+ linux_platform_name="$(get_linux_platform_name)" || true
204
+
205
+ if [ "$linux_platform_name" = "rhel.6" ]; then
206
+ echo $linux_platform_name
207
+ return 0
208
+ elif is_musl_based_distro; then
209
+ echo "linux-musl"
210
+ return 0
211
+ elif [ "$linux_platform_name" = "linux-musl" ]; then
212
+ echo "linux-musl"
213
+ return 0
214
+ else
215
+ echo "linux"
216
+ return 0
217
+ fi
218
+ fi
219
+
220
+ say_err "OS name could not be detected: UName = $uname"
221
+ return 1
222
+ }
223
+
224
+ machine_has() {
225
+ eval $invocation
226
+
227
+ command -v "$1" > /dev/null 2>&1
228
+ return $?
229
+ }
230
+
231
+ check_min_reqs() {
232
+ local hasMinimum=false
233
+ if machine_has "curl"; then
234
+ hasMinimum=true
235
+ elif machine_has "wget"; then
236
+ hasMinimum=true
237
+ fi
238
+
239
+ if [ "$hasMinimum" = "false" ]; then
240
+ say_err "curl (recommended) or wget are required to download dotnet. Install missing prerequisite to proceed."
241
+ return 1
242
+ fi
243
+ return 0
244
+ }
245
+
246
+ # args:
247
+ # input - $1
248
+ to_lowercase() {
249
+ #eval $invocation
250
+
251
+ echo "$1" | tr '[:upper:]' '[:lower:]'
252
+ return 0
253
+ }
254
+
255
+ # args:
256
+ # input - $1
257
+ remove_trailing_slash() {
258
+ #eval $invocation
259
+
260
+ local input="${1:-}"
261
+ echo "${input%/}"
262
+ return 0
263
+ }
264
+
265
+ # args:
266
+ # input - $1
267
+ remove_beginning_slash() {
268
+ #eval $invocation
269
+
270
+ local input="${1:-}"
271
+ echo "${input#/}"
272
+ return 0
273
+ }
274
+
275
+ # args:
276
+ # root_path - $1
277
+ # child_path - $2 - this parameter can be empty
278
+ combine_paths() {
279
+ eval $invocation
280
+
281
+ # TODO: Consider making it work with any number of paths. For now:
282
+ if [ ! -z "${3:-}" ]; then
283
+ say_err "combine_paths: Function takes two parameters."
284
+ return 1
285
+ fi
286
+
287
+ local root_path="$(remove_trailing_slash "$1")"
288
+ local child_path="$(remove_beginning_slash "${2:-}")"
289
+ say_verbose "combine_paths: root_path=$root_path"
290
+ say_verbose "combine_paths: child_path=$child_path"
291
+ echo "$root_path/$child_path"
292
+ return 0
293
+ }
294
+
295
+ get_machine_architecture() {
296
+ eval $invocation
297
+
298
+ if command -v uname > /dev/null; then
299
+ CPUName=$(uname -m)
300
+ case $CPUName in
301
+ armv1*|armv2*|armv3*|armv4*|armv5*|armv6*)
302
+ echo "armv6-or-below"
303
+ return 0
304
+ ;;
305
+ armv*l)
306
+ echo "arm"
307
+ return 0
308
+ ;;
309
+ aarch64|arm64)
310
+ if [ "$(getconf LONG_BIT)" -lt 64 ]; then
311
+ # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS)
312
+ echo "arm"
313
+ return 0
314
+ fi
315
+ echo "arm64"
316
+ return 0
317
+ ;;
318
+ s390x)
319
+ echo "s390x"
320
+ return 0
321
+ ;;
322
+ ppc64le)
323
+ echo "ppc64le"
324
+ return 0
325
+ ;;
326
+ loongarch64)
327
+ echo "loongarch64"
328
+ return 0
329
+ ;;
330
+ riscv64)
331
+ echo "riscv64"
332
+ return 0
333
+ ;;
334
+ powerpc|ppc)
335
+ echo "ppc"
336
+ return 0
337
+ ;;
338
+ esac
339
+ fi
340
+
341
+ # Always default to 'x64'
342
+ echo "x64"
343
+ return 0
344
+ }
345
+
346
+ # args:
347
+ # architecture - $1
348
+ get_normalized_architecture_from_architecture() {
349
+ eval $invocation
350
+
351
+ local architecture="$(to_lowercase "$1")"
352
+
353
+ if [[ $architecture == \<auto\> ]]; then
354
+ machine_architecture="$(get_machine_architecture)"
355
+ if [[ "$machine_architecture" == "armv6-or-below" ]]; then
356
+ say_err "Architecture \`$machine_architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
357
+ return 1
358
+ fi
359
+
360
+ echo $machine_architecture
361
+ return 0
362
+ fi
363
+
364
+ case "$architecture" in
365
+ amd64|x64)
366
+ echo "x64"
367
+ return 0
368
+ ;;
369
+ arm)
370
+ echo "arm"
371
+ return 0
372
+ ;;
373
+ arm64)
374
+ echo "arm64"
375
+ return 0
376
+ ;;
377
+ s390x)
378
+ echo "s390x"
379
+ return 0
380
+ ;;
381
+ ppc64le)
382
+ echo "ppc64le"
383
+ return 0
384
+ ;;
385
+ loongarch64)
386
+ echo "loongarch64"
387
+ return 0
388
+ ;;
389
+ esac
390
+
391
+ say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues"
392
+ return 1
393
+ }
394
+
395
+ # args:
396
+ # version - $1
397
+ # channel - $2
398
+ # architecture - $3
399
+ get_normalized_architecture_for_specific_sdk_version() {
400
+ eval $invocation
401
+
402
+ local is_version_support_arm64="$(is_arm64_supported "$1")"
403
+ local is_channel_support_arm64="$(is_arm64_supported "$2")"
404
+ local architecture="$3";
405
+ local osname="$(get_current_os_name)"
406
+
407
+ if [ "$osname" == "osx" ] && [ "$architecture" == "arm64" ] && { [ "$is_version_support_arm64" = false ] || [ "$is_channel_support_arm64" = false ]; }; then
408
+ #check if rosetta is installed
409
+ if [ "$(/usr/bin/pgrep oahd >/dev/null 2>&1;echo $?)" -eq 0 ]; then
410
+ say_verbose "Changing user architecture from '$architecture' to 'x64' because .NET SDKs prior to version 6.0 do not support arm64."
411
+ echo "x64"
412
+ return 0;
413
+ else
414
+ say_err "Architecture \`$architecture\` is not supported for .NET SDK version \`$version\`. Please install Rosetta to allow emulation of the \`$architecture\` .NET SDK on this platform"
415
+ return 1
416
+ fi
417
+ fi
418
+
419
+ echo "$architecture"
420
+ return 0
421
+ }
422
+
423
+ # args:
424
+ # version or channel - $1
425
+ is_arm64_supported() {
426
+ # Extract the major version by splitting on the dot
427
+ major_version="${1%%.*}"
428
+
429
+ # Check if the major version is a valid number and less than 6
430
+ case "$major_version" in
431
+ [0-9]*)
432
+ if [ "$major_version" -lt 6 ]; then
433
+ echo false
434
+ return 0
435
+ fi
436
+ ;;
437
+ esac
438
+
439
+ echo true
440
+ return 0
441
+ }
442
+
443
+ # args:
444
+ # user_defined_os - $1
445
+ get_normalized_os() {
446
+ eval $invocation
447
+
448
+ local osname="$(to_lowercase "$1")"
449
+ if [ ! -z "$osname" ]; then
450
+ case "$osname" in
451
+ osx | freebsd | rhel.6 | linux-musl | linux)
452
+ echo "$osname"
453
+ return 0
454
+ ;;
455
+ macos)
456
+ osname='osx'
457
+ echo "$osname"
458
+ return 0
459
+ ;;
460
+ *)
461
+ say_err "'$user_defined_os' is not a supported value for --os option, supported values are: osx, macos, linux, linux-musl, freebsd, rhel.6. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
462
+ return 1
463
+ ;;
464
+ esac
465
+ else
466
+ osname="$(get_current_os_name)" || return 1
467
+ fi
468
+ echo "$osname"
469
+ return 0
470
+ }
471
+
472
+ # args:
473
+ # quality - $1
474
+ get_normalized_quality() {
475
+ eval $invocation
476
+
477
+ local quality="$(to_lowercase "$1")"
478
+ if [ ! -z "$quality" ]; then
479
+ case "$quality" in
480
+ daily | preview)
481
+ echo "$quality"
482
+ return 0
483
+ ;;
484
+ ga)
485
+ #ga quality is available without specifying quality, so normalizing it to empty
486
+ return 0
487
+ ;;
488
+ *)
489
+ say_err "'$quality' is not a supported value for --quality option. Supported values are: daily, preview, ga. If you think this is a bug, report it at https://github.com/dotnet/install-scripts/issues."
490
+ return 1
491
+ ;;
492
+ esac
493
+ fi
494
+ return 0
495
+ }
496
+
497
+ # args:
498
+ # channel - $1
499
+ get_normalized_channel() {
500
+ eval $invocation
501
+
502
+ local channel="$(to_lowercase "$1")"
503
+
504
+ if [[ $channel == current ]]; then
505
+ say_warning 'Value "Current" is deprecated for -Channel option. Use "STS" instead.'
506
+ fi
507
+
508
+ if [[ $channel == release/* ]]; then
509
+ say_warning 'Using branch name with -Channel option is no longer supported with newer releases. Use -Quality option with a channel in X.Y format instead.';
510
+ fi
511
+
512
+ if [ ! -z "$channel" ]; then
513
+ case "$channel" in
514
+ lts)
515
+ echo "LTS"
516
+ return 0
517
+ ;;
518
+ sts)
519
+ echo "STS"
520
+ return 0
521
+ ;;
522
+ current)
523
+ echo "STS"
524
+ return 0
525
+ ;;
526
+ *)
527
+ echo "$channel"
528
+ return 0
529
+ ;;
530
+ esac
531
+ fi
532
+
533
+ return 0
534
+ }
535
+
536
+ # args:
537
+ # runtime - $1
538
+ get_normalized_product() {
539
+ eval $invocation
540
+
541
+ local product=""
542
+ local runtime="$(to_lowercase "$1")"
543
+ if [[ "$runtime" == "dotnet" ]]; then
544
+ product="dotnet-runtime"
545
+ elif [[ "$runtime" == "aspnetcore" ]]; then
546
+ product="aspnetcore-runtime"
547
+ elif [ -z "$runtime" ]; then
548
+ product="dotnet-sdk"
549
+ fi
550
+ echo "$product"
551
+ return 0
552
+ }
553
+
554
+ # The version text returned from the feeds is a 1-line or 2-line string:
555
+ # For the SDK and the dotnet runtime (2 lines):
556
+ # Line 1: # commit_hash
557
+ # Line 2: # 4-part version
558
+ # For the aspnetcore runtime (1 line):
559
+ # Line 1: # 4-part version
560
+
561
+ # args:
562
+ # version_text - stdin
563
+ get_version_from_latestversion_file_content() {
564
+ eval $invocation
565
+
566
+ cat | tail -n 1 | sed 's/\r$//'
567
+ return 0
568
+ }
569
+
570
+ # args:
571
+ # install_root - $1
572
+ # relative_path_to_package - $2
573
+ # specific_version - $3
574
+ is_dotnet_package_installed() {
575
+ eval $invocation
576
+
577
+ local install_root="$1"
578
+ local relative_path_to_package="$2"
579
+ local specific_version="${3//[$'\t\r\n']}"
580
+
581
+ local dotnet_package_path="$(combine_paths "$(combine_paths "$install_root" "$relative_path_to_package")" "$specific_version")"
582
+ say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path"
583
+
584
+ if [ -d "$dotnet_package_path" ]; then
585
+ return 0
586
+ else
587
+ return 1
588
+ fi
589
+ }
590
+
591
+ # args:
592
+ # downloaded file - $1
593
+ # remote_file_size - $2
594
+ validate_remote_local_file_sizes()
595
+ {
596
+ eval $invocation
597
+
598
+ local downloaded_file="$1"
599
+ local remote_file_size="$2"
600
+ local file_size=''
601
+
602
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
603
+ file_size="$(stat -c '%s' "$downloaded_file")"
604
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
605
+ # hardcode in order to avoid conflicts with GNU stat
606
+ file_size="$(/usr/bin/stat -f '%z' "$downloaded_file")"
607
+ fi
608
+
609
+ if [ -n "$file_size" ]; then
610
+ say "Downloaded file size is $file_size bytes."
611
+
612
+ if [ -n "$remote_file_size" ] && [ -n "$file_size" ]; then
613
+ if [ "$remote_file_size" -ne "$file_size" ]; then
614
+ say "The remote and local file sizes are not equal. The remote file size is $remote_file_size bytes and the local size is $file_size bytes. The local package may be corrupted."
615
+ else
616
+ say "The remote and local file sizes are equal."
617
+ fi
618
+ fi
619
+
620
+ else
621
+ say "Either downloaded or local package size can not be measured. One of them may be corrupted."
622
+ fi
623
+ }
624
+
625
+ # args:
626
+ # azure_feed - $1
627
+ # channel - $2
628
+ # normalized_architecture - $3
629
+ get_version_from_latestversion_file() {
630
+ eval $invocation
631
+
632
+ local azure_feed="$1"
633
+ local channel="$2"
634
+ local normalized_architecture="$3"
635
+
636
+ local version_file_url=null
637
+ if [[ "$runtime" == "dotnet" ]]; then
638
+ version_file_url="$azure_feed/Runtime/$channel/latest.version"
639
+ elif [[ "$runtime" == "aspnetcore" ]]; then
640
+ version_file_url="$azure_feed/aspnetcore/Runtime/$channel/latest.version"
641
+ elif [ -z "$runtime" ]; then
642
+ version_file_url="$azure_feed/Sdk/$channel/latest.version"
643
+ else
644
+ say_err "Invalid value for \$runtime"
645
+ return 1
646
+ fi
647
+ say_verbose "get_version_from_latestversion_file: latest url: $version_file_url"
648
+
649
+ download "$version_file_url" || return $?
650
+ return 0
651
+ }
652
+
653
+ # args:
654
+ # json_file - $1
655
+ parse_globaljson_file_for_version() {
656
+ eval $invocation
657
+
658
+ local json_file="$1"
659
+ if [ ! -f "$json_file" ]; then
660
+ say_err "Unable to find \`$json_file\`"
661
+ return 1
662
+ fi
663
+
664
+ sdk_section=$(cat "$json_file" | tr -d "\r" | awk '/"sdk"/,/}/')
665
+ if [ -z "$sdk_section" ]; then
666
+ say_err "Unable to parse the SDK node in \`$json_file\`"
667
+ return 1
668
+ fi
669
+
670
+ sdk_list=$(echo $sdk_section | awk -F"[{}]" '{print $2}')
671
+ sdk_list=${sdk_list//[\" ]/}
672
+ sdk_list=${sdk_list//,/$'\n'}
673
+
674
+ local version_info=""
675
+ while read -r line; do
676
+ IFS=:
677
+ while read -r key value; do
678
+ if [[ "$key" == "version" ]]; then
679
+ version_info=$value
680
+ fi
681
+ done <<< "$line"
682
+ done <<< "$sdk_list"
683
+ if [ -z "$version_info" ]; then
684
+ say_err "Unable to find the SDK:version node in \`$json_file\`"
685
+ return 1
686
+ fi
687
+
688
+ unset IFS;
689
+ echo "$version_info"
690
+ return 0
691
+ }
692
+
693
+ # args:
694
+ # azure_feed - $1
695
+ # channel - $2
696
+ # normalized_architecture - $3
697
+ # version - $4
698
+ # json_file - $5
699
+ get_specific_version_from_version() {
700
+ eval $invocation
701
+
702
+ local azure_feed="$1"
703
+ local channel="$2"
704
+ local normalized_architecture="$3"
705
+ local version="$(to_lowercase "$4")"
706
+ local json_file="$5"
707
+
708
+ if [ -z "$json_file" ]; then
709
+ if [[ "$version" == "latest" ]]; then
710
+ local version_info
711
+ version_info="$(get_version_from_latestversion_file "$azure_feed" "$channel" "$normalized_architecture" false)" || return 1
712
+ say_verbose "get_specific_version_from_version: version_info=$version_info"
713
+ echo "$version_info" | get_version_from_latestversion_file_content
714
+ return 0
715
+ else
716
+ echo "$version"
717
+ return 0
718
+ fi
719
+ else
720
+ local version_info
721
+ version_info="$(parse_globaljson_file_for_version "$json_file")" || return 1
722
+ echo "$version_info"
723
+ return 0
724
+ fi
725
+ }
726
+
727
+ # args:
728
+ # azure_feed - $1
729
+ # channel - $2
730
+ # normalized_architecture - $3
731
+ # specific_version - $4
732
+ # normalized_os - $5
733
+ construct_download_link() {
734
+ eval $invocation
735
+
736
+ local azure_feed="$1"
737
+ local channel="$2"
738
+ local normalized_architecture="$3"
739
+ local specific_version="${4//[$'\t\r\n']}"
740
+ local specific_product_version="$(get_specific_product_version "$1" "$4")"
741
+ local osname="$5"
742
+
743
+ local download_link=null
744
+ if [[ "$runtime" == "dotnet" ]]; then
745
+ download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_product_version-$osname-$normalized_architecture.tar.gz"
746
+ elif [[ "$runtime" == "aspnetcore" ]]; then
747
+ download_link="$azure_feed/aspnetcore/Runtime/$specific_version/aspnetcore-runtime-$specific_product_version-$osname-$normalized_architecture.tar.gz"
748
+ elif [ -z "$runtime" ]; then
749
+ download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_product_version-$osname-$normalized_architecture.tar.gz"
750
+ else
751
+ return 1
752
+ fi
753
+
754
+ echo "$download_link"
755
+ return 0
756
+ }
757
+
758
+ # args:
759
+ # azure_feed - $1
760
+ # specific_version - $2
761
+ # download link - $3 (optional)
762
+ get_specific_product_version() {
763
+ # If we find a 'productVersion.txt' at the root of any folder, we'll use its contents
764
+ # to resolve the version of what's in the folder, superseding the specified version.
765
+ # if 'productVersion.txt' is missing but download link is already available, product version will be taken from download link
766
+ eval $invocation
767
+
768
+ local azure_feed="$1"
769
+ local specific_version="${2//[$'\t\r\n']}"
770
+ local package_download_link=""
771
+ if [ $# -gt 2 ]; then
772
+ local package_download_link="$3"
773
+ fi
774
+ local specific_product_version=null
775
+
776
+ # Try to get the version number, using the productVersion.txt file located next to the installer file.
777
+ local download_links=($(get_specific_product_version_url "$azure_feed" "$specific_version" true "$package_download_link")
778
+ $(get_specific_product_version_url "$azure_feed" "$specific_version" false "$package_download_link"))
779
+
780
+ for download_link in "${download_links[@]}"
781
+ do
782
+ say_verbose "Checking for the existence of $download_link"
783
+
784
+ if machine_has "curl"
785
+ then
786
+ if ! specific_product_version=$(curl -sL --fail "${download_link}${feed_credential}" 2>&1); then
787
+ continue
788
+ else
789
+ echo "${specific_product_version//[$'\t\r\n']}"
790
+ return 0
791
+ fi
792
+
793
+ elif machine_has "wget"
794
+ then
795
+ specific_product_version=$(wget -qO- "${download_link}${feed_credential}" 2>&1)
796
+ if [ $? = 0 ]; then
797
+ echo "${specific_product_version//[$'\t\r\n']}"
798
+ return 0
799
+ fi
800
+ fi
801
+ done
802
+
803
+ # Getting the version number with productVersion.txt has failed. Try parsing the download link for a version number.
804
+ say_verbose "Failed to get the version using productVersion.txt file. Download link will be parsed instead."
805
+ specific_product_version="$(get_product_specific_version_from_download_link "$package_download_link" "$specific_version")"
806
+ echo "${specific_product_version//[$'\t\r\n']}"
807
+ return 0
808
+ }
809
+
810
+ # args:
811
+ # azure_feed - $1
812
+ # specific_version - $2
813
+ # is_flattened - $3
814
+ # download link - $4 (optional)
815
+ get_specific_product_version_url() {
816
+ eval $invocation
817
+
818
+ local azure_feed="$1"
819
+ local specific_version="$2"
820
+ local is_flattened="$3"
821
+ local package_download_link=""
822
+ if [ $# -gt 3 ]; then
823
+ local package_download_link="$4"
824
+ fi
825
+
826
+ local pvFileName="productVersion.txt"
827
+ if [ "$is_flattened" = true ]; then
828
+ if [ -z "$runtime" ]; then
829
+ pvFileName="sdk-productVersion.txt"
830
+ elif [[ "$runtime" == "dotnet" ]]; then
831
+ pvFileName="runtime-productVersion.txt"
832
+ else
833
+ pvFileName="$runtime-productVersion.txt"
834
+ fi
835
+ fi
836
+
837
+ local download_link=null
838
+
839
+ if [ -z "$package_download_link" ]; then
840
+ if [[ "$runtime" == "dotnet" ]]; then
841
+ download_link="$azure_feed/Runtime/$specific_version/${pvFileName}"
842
+ elif [[ "$runtime" == "aspnetcore" ]]; then
843
+ download_link="$azure_feed/aspnetcore/Runtime/$specific_version/${pvFileName}"
844
+ elif [ -z "$runtime" ]; then
845
+ download_link="$azure_feed/Sdk/$specific_version/${pvFileName}"
846
+ else
847
+ return 1
848
+ fi
849
+ else
850
+ download_link="${package_download_link%/*}/${pvFileName}"
851
+ fi
852
+
853
+ say_verbose "Constructed productVersion link: $download_link"
854
+ echo "$download_link"
855
+ return 0
856
+ }
857
+
858
+ # args:
859
+ # download link - $1
860
+ # specific version - $2
861
+ get_product_specific_version_from_download_link()
862
+ {
863
+ eval $invocation
864
+
865
+ local download_link="$1"
866
+ local specific_version="$2"
867
+ local specific_product_version=""
868
+
869
+ if [ -z "$download_link" ]; then
870
+ echo "$specific_version"
871
+ return 0
872
+ fi
873
+
874
+ #get filename
875
+ filename="${download_link##*/}"
876
+
877
+ #product specific version follows the product name
878
+ #for filename 'dotnet-sdk-3.1.404-linux-x64.tar.gz': the product version is 3.1.404
879
+ IFS='-'
880
+ read -ra filename_elems <<< "$filename"
881
+ count=${#filename_elems[@]}
882
+ if [[ "$count" -gt 2 ]]; then
883
+ specific_product_version="${filename_elems[2]}"
884
+ else
885
+ specific_product_version=$specific_version
886
+ fi
887
+ unset IFS;
888
+ echo "$specific_product_version"
889
+ return 0
890
+ }
891
+
892
+ # args:
893
+ # azure_feed - $1
894
+ # channel - $2
895
+ # normalized_architecture - $3
896
+ # specific_version - $4
897
+ construct_legacy_download_link() {
898
+ eval $invocation
899
+
900
+ local azure_feed="$1"
901
+ local channel="$2"
902
+ local normalized_architecture="$3"
903
+ local specific_version="${4//[$'\t\r\n']}"
904
+
905
+ local distro_specific_osname
906
+ distro_specific_osname="$(get_legacy_os_name)" || return 1
907
+
908
+ local legacy_download_link=null
909
+ if [[ "$runtime" == "dotnet" ]]; then
910
+ legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
911
+ elif [ -z "$runtime" ]; then
912
+ legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
913
+ else
914
+ return 1
915
+ fi
916
+
917
+ echo "$legacy_download_link"
918
+ return 0
919
+ }
920
+
921
+ get_user_install_path() {
922
+ eval $invocation
923
+
924
+ if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then
925
+ echo "$DOTNET_INSTALL_DIR"
926
+ else
927
+ echo "$HOME/.dotnet"
928
+ fi
929
+ return 0
930
+ }
931
+
932
+ # args:
933
+ # install_dir - $1
934
+ resolve_installation_path() {
935
+ eval $invocation
936
+
937
+ local install_dir=$1
938
+ if [ "$install_dir" = "<auto>" ]; then
939
+ local user_install_path="$(get_user_install_path)"
940
+ say_verbose "resolve_installation_path: user_install_path=$user_install_path"
941
+ echo "$user_install_path"
942
+ return 0
943
+ fi
944
+
945
+ echo "$install_dir"
946
+ return 0
947
+ }
948
+
949
+ # args:
950
+ # relative_or_absolute_path - $1
951
+ get_absolute_path() {
952
+ eval $invocation
953
+
954
+ local relative_or_absolute_path=$1
955
+ echo "$(cd "$(dirname "$1")" && pwd -P)/$(basename "$1")"
956
+ return 0
957
+ }
958
+
959
+ # args:
960
+ # override - $1 (boolean, true or false)
961
+ get_cp_options() {
962
+ eval $invocation
963
+
964
+ local override="$1"
965
+ local override_switch=""
966
+
967
+ if [ "$override" = false ]; then
968
+ override_switch="-n"
969
+
970
+ # create temporary files to check if 'cp -u' is supported
971
+ tmp_dir="$(mktemp -d)"
972
+ tmp_file="$tmp_dir/testfile"
973
+ tmp_file2="$tmp_dir/testfile2"
974
+
975
+ touch "$tmp_file"
976
+
977
+ # use -u instead of -n if it's available
978
+ if cp -u "$tmp_file" "$tmp_file2" 2>/dev/null; then
979
+ override_switch="-u"
980
+ fi
981
+
982
+ # clean up
983
+ rm -f "$tmp_file" "$tmp_file2"
984
+ rm -rf "$tmp_dir"
985
+ fi
986
+
987
+ echo "$override_switch"
988
+ }
989
+
990
+ # args:
991
+ # input_files - stdin
992
+ # root_path - $1
993
+ # out_path - $2
994
+ # override - $3
995
+ copy_files_or_dirs_from_list() {
996
+ eval $invocation
997
+
998
+ local root_path="$(remove_trailing_slash "$1")"
999
+ local out_path="$(remove_trailing_slash "$2")"
1000
+ local override="$3"
1001
+ local override_switch="$(get_cp_options "$override")"
1002
+
1003
+ cat | uniq | while read -r file_path; do
1004
+ local path="$(remove_beginning_slash "${file_path#$root_path}")"
1005
+ local target="$out_path/$path"
1006
+ if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then
1007
+ mkdir -p "$out_path/$(dirname "$path")"
1008
+ if [ -d "$target" ]; then
1009
+ rm -rf "$target"
1010
+ fi
1011
+ cp -R $override_switch "$root_path/$path" "$target"
1012
+ fi
1013
+ done
1014
+ }
1015
+
1016
+ # args:
1017
+ # zip_uri - $1
1018
+ get_remote_file_size() {
1019
+ local zip_uri="$1"
1020
+
1021
+ if machine_has "curl"; then
1022
+ file_size=$(curl -sI "$zip_uri" | grep -i content-length | awk '{ num = $2 + 0; print num }')
1023
+ elif machine_has "wget"; then
1024
+ file_size=$(wget --spider --server-response -O /dev/null "$zip_uri" 2>&1 | grep -i 'Content-Length:' | awk '{ num = $2 + 0; print num }')
1025
+ else
1026
+ say "Neither curl nor wget is available on this system."
1027
+ return
1028
+ fi
1029
+
1030
+ if [ -n "$file_size" ]; then
1031
+ say "Remote file $zip_uri size is $file_size bytes."
1032
+ echo "$file_size"
1033
+ else
1034
+ say_verbose "Content-Length header was not extracted for $zip_uri."
1035
+ echo ""
1036
+ fi
1037
+ }
1038
+
1039
+ # args:
1040
+ # zip_path - $1
1041
+ # out_path - $2
1042
+ # remote_file_size - $3
1043
+ extract_dotnet_package() {
1044
+ eval $invocation
1045
+
1046
+ local zip_path="$1"
1047
+ local out_path="$2"
1048
+ local remote_file_size="$3"
1049
+
1050
+ local temp_out_path="$(mktemp -d "$temporary_file_template")"
1051
+
1052
+ local failed=false
1053
+ tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true
1054
+
1055
+ local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/'
1056
+ find "$temp_out_path" -type f | grep -Eo "$folders_with_version_regex" | sort | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" false
1057
+ find "$temp_out_path" -type f | grep -Ev "$folders_with_version_regex" | copy_files_or_dirs_from_list "$temp_out_path" "$out_path" "$override_non_versioned_files"
1058
+
1059
+ validate_remote_local_file_sizes "$zip_path" "$remote_file_size"
1060
+
1061
+ rm -rf "$temp_out_path"
1062
+ if [ -z ${keep_zip+x} ]; then
1063
+ rm -f "$zip_path" && say_verbose "Temporary archive file $zip_path was removed"
1064
+ fi
1065
+
1066
+ if [ "$failed" = true ]; then
1067
+ say_err "Extraction failed"
1068
+ return 1
1069
+ fi
1070
+ return 0
1071
+ }
1072
+
1073
+ # args:
1074
+ # remote_path - $1
1075
+ # disable_feed_credential - $2
1076
+ get_http_header()
1077
+ {
1078
+ eval $invocation
1079
+ local remote_path="$1"
1080
+ local disable_feed_credential="$2"
1081
+
1082
+ local failed=false
1083
+ local response
1084
+ if machine_has "curl"; then
1085
+ get_http_header_curl $remote_path $disable_feed_credential || failed=true
1086
+ elif machine_has "wget"; then
1087
+ get_http_header_wget $remote_path $disable_feed_credential || failed=true
1088
+ else
1089
+ failed=true
1090
+ fi
1091
+ if [ "$failed" = true ]; then
1092
+ say_verbose "Failed to get HTTP header: '$remote_path'."
1093
+ return 1
1094
+ fi
1095
+ return 0
1096
+ }
1097
+
1098
+ # args:
1099
+ # remote_path - $1
1100
+ # disable_feed_credential - $2
1101
+ get_http_header_curl() {
1102
+ eval $invocation
1103
+ local remote_path="$1"
1104
+ local disable_feed_credential="$2"
1105
+
1106
+ remote_path_with_credential="$remote_path"
1107
+ if [ "$disable_feed_credential" = false ]; then
1108
+ remote_path_with_credential+="$feed_credential"
1109
+ fi
1110
+
1111
+ curl_options="-I -sSL --retry 5 --retry-delay 2 --connect-timeout 15 "
1112
+ curl $curl_options "$remote_path_with_credential" 2>&1 || return 1
1113
+ return 0
1114
+ }
1115
+
1116
+ # args:
1117
+ # remote_path - $1
1118
+ # disable_feed_credential - $2
1119
+ get_http_header_wget() {
1120
+ eval $invocation
1121
+ local remote_path="$1"
1122
+ local disable_feed_credential="$2"
1123
+ local wget_options="-q -S --spider --tries 5 "
1124
+
1125
+ local wget_options_extra=''
1126
+
1127
+ # Test for options that aren't supported on all wget implementations.
1128
+ if [[ $(wget -h 2>&1 | grep -E 'waitretry|connect-timeout') ]]; then
1129
+ wget_options_extra="--waitretry 2 --connect-timeout 15 "
1130
+ else
1131
+ say "wget extra options are unavailable for this environment"
1132
+ fi
1133
+
1134
+ remote_path_with_credential="$remote_path"
1135
+ if [ "$disable_feed_credential" = false ]; then
1136
+ remote_path_with_credential+="$feed_credential"
1137
+ fi
1138
+
1139
+ wget $wget_options $wget_options_extra "$remote_path_with_credential" 2>&1
1140
+
1141
+ return $?
1142
+ }
1143
+
1144
+ # args:
1145
+ # remote_path - $1
1146
+ # [out_path] - $2 - stdout if not provided
1147
+ download() {
1148
+ eval $invocation
1149
+
1150
+ local remote_path="$1"
1151
+ local out_path="${2:-}"
1152
+
1153
+ if [[ "$remote_path" != "http"* ]]; then
1154
+ cp "$remote_path" "$out_path"
1155
+ return $?
1156
+ fi
1157
+
1158
+ local failed=false
1159
+ local attempts=0
1160
+ while [ $attempts -lt 3 ]; do
1161
+ attempts=$((attempts+1))
1162
+ failed=false
1163
+ if machine_has "curl"; then
1164
+ downloadcurl "$remote_path" "$out_path" || failed=true
1165
+ elif machine_has "wget"; then
1166
+ downloadwget "$remote_path" "$out_path" || failed=true
1167
+ else
1168
+ say_err "Missing dependency: neither curl nor wget was found."
1169
+ exit 1
1170
+ fi
1171
+
1172
+ if [ "$failed" = false ] || [ $attempts -ge 3 ] || { [ -n "${http_code-}" ] && [ "${http_code}" = "404" ]; }; then
1173
+ break
1174
+ fi
1175
+
1176
+ say "Download attempt #$attempts has failed: ${http_code-} ${download_error_msg-}"
1177
+ say "Attempt #$((attempts+1)) will start in $((attempts*10)) seconds."
1178
+ sleep $((attempts*10))
1179
+ done
1180
+
1181
+ if [ "$failed" = true ]; then
1182
+ say_verbose "Download failed: $remote_path"
1183
+ return 1
1184
+ fi
1185
+ return 0
1186
+ }
1187
+
1188
+ # Updates global variables $http_code and $download_error_msg
1189
+ downloadcurl() {
1190
+ eval $invocation
1191
+ unset http_code
1192
+ unset download_error_msg
1193
+ local remote_path="$1"
1194
+ local out_path="${2:-}"
1195
+ # Append feed_credential as late as possible before calling curl to avoid logging feed_credential
1196
+ # Avoid passing URI with credentials to functions: note, most of them echoing parameters of invocation in verbose output.
1197
+ local remote_path_with_credential="${remote_path}${feed_credential}"
1198
+ local curl_options="--retry 20 --retry-delay 2 --connect-timeout 15 -sSL -f --create-dirs "
1199
+ local curl_exit_code=0;
1200
+ if [ -z "$out_path" ]; then
1201
+ curl_output=$(curl $curl_options "$remote_path_with_credential" 2>&1)
1202
+ curl_exit_code=$?
1203
+ echo "$curl_output"
1204
+ else
1205
+ curl_output=$(curl $curl_options -o "$out_path" "$remote_path_with_credential" 2>&1)
1206
+ curl_exit_code=$?
1207
+ fi
1208
+
1209
+ # Regression in curl causes curl with --retry to return a 0 exit code even when it fails to download a file - https://github.com/curl/curl/issues/17554
1210
+ if [ $curl_exit_code -eq 0 ] && echo "$curl_output" | grep -q "^curl: ([0-9]*) "; then
1211
+ curl_exit_code=$(echo "$curl_output" | sed 's/curl: (\([0-9]*\)).*/\1/')
1212
+ fi
1213
+
1214
+ if [ $curl_exit_code -gt 0 ]; then
1215
+ download_error_msg="Unable to download $remote_path."
1216
+ # Check for curl timeout codes
1217
+ if [[ $curl_exit_code == 7 || $curl_exit_code == 28 ]]; then
1218
+ download_error_msg+=" Failed to reach the server: connection timeout."
1219
+ else
1220
+ local disable_feed_credential=false
1221
+ local response=$(get_http_header_curl $remote_path $disable_feed_credential)
1222
+ http_code=$( echo "$response" | awk '/^HTTP/{print $2}' | tail -1 )
1223
+ if [[ ! -z $http_code && $http_code != 2* ]]; then
1224
+ download_error_msg+=" Returned HTTP status code: $http_code."
1225
+ fi
1226
+ fi
1227
+ say_verbose "$download_error_msg"
1228
+ return 1
1229
+ fi
1230
+ return 0
1231
+ }
1232
+
1233
+
1234
+ # Updates global variables $http_code and $download_error_msg
1235
+ downloadwget() {
1236
+ eval $invocation
1237
+ unset http_code
1238
+ unset download_error_msg
1239
+ local remote_path="$1"
1240
+ local out_path="${2:-}"
1241
+ # Append feed_credential as late as possible before calling wget to avoid logging feed_credential
1242
+ local remote_path_with_credential="${remote_path}${feed_credential}"
1243
+ local wget_options="--tries 20 "
1244
+
1245
+ local wget_options_extra=''
1246
+ local wget_result=''
1247
+
1248
+ # Test for options that aren't supported on all wget implementations.
1249
+ if [[ $(wget -h 2>&1 | grep -E 'waitretry|connect-timeout') ]]; then
1250
+ wget_options_extra="--waitretry 2 --connect-timeout 15 "
1251
+ else
1252
+ say "wget extra options are unavailable for this environment"
1253
+ fi
1254
+
1255
+ if [ -z "$out_path" ]; then
1256
+ wget -q $wget_options $wget_options_extra -O - "$remote_path_with_credential" 2>&1
1257
+ wget_result=$?
1258
+ else
1259
+ wget $wget_options $wget_options_extra -O "$out_path" "$remote_path_with_credential" 2>&1
1260
+ wget_result=$?
1261
+ fi
1262
+
1263
+ if [[ $wget_result != 0 ]]; then
1264
+ local disable_feed_credential=false
1265
+ local response=$(get_http_header_wget $remote_path $disable_feed_credential)
1266
+ http_code=$( echo "$response" | awk '/^ HTTP/{print $2}' | tail -1 )
1267
+ download_error_msg="Unable to download $remote_path."
1268
+ if [[ ! -z $http_code && $http_code != 2* ]]; then
1269
+ download_error_msg+=" Returned HTTP status code: $http_code."
1270
+ # wget exit code 4 stands for network-issue
1271
+ elif [[ $wget_result == 4 ]]; then
1272
+ download_error_msg+=" Failed to reach the server: connection timeout."
1273
+ fi
1274
+ say_verbose "$download_error_msg"
1275
+ return 1
1276
+ fi
1277
+
1278
+ return 0
1279
+ }
1280
+
1281
+ get_download_link_from_aka_ms() {
1282
+ eval $invocation
1283
+
1284
+ #quality is not supported for LTS or STS channel
1285
+ #STS maps to current
1286
+ if [[ ! -z "$normalized_quality" && ("$normalized_channel" == "LTS" || "$normalized_channel" == "STS") ]]; then
1287
+ normalized_quality=""
1288
+ say_warning "Specifying quality for STS or LTS channel is not supported, the quality will be ignored."
1289
+ fi
1290
+
1291
+ say_verbose "Retrieving primary payload URL from aka.ms for channel: '$normalized_channel', quality: '$normalized_quality', product: '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
1292
+
1293
+ #construct aka.ms link
1294
+ aka_ms_link="https://aka.ms/dotnet"
1295
+ if [ "$internal" = true ]; then
1296
+ aka_ms_link="$aka_ms_link/internal"
1297
+ fi
1298
+ aka_ms_link="$aka_ms_link/$normalized_channel"
1299
+ if [[ ! -z "$normalized_quality" ]]; then
1300
+ aka_ms_link="$aka_ms_link/$normalized_quality"
1301
+ fi
1302
+ aka_ms_link="$aka_ms_link/$normalized_product-$normalized_os-$normalized_architecture.tar.gz"
1303
+ say_verbose "Constructed aka.ms link: '$aka_ms_link'."
1304
+
1305
+ #get HTTP response
1306
+ #do not pass credentials as a part of the $aka_ms_link and do not apply credentials in the get_http_header function
1307
+ #otherwise the redirect link would have credentials as well
1308
+ #it would result in applying credentials twice to the resulting link and thus breaking it, and in echoing credentials to the output as a part of redirect link
1309
+ disable_feed_credential=true
1310
+ response="$(get_http_header $aka_ms_link $disable_feed_credential)"
1311
+
1312
+ say_verbose "Received response: $response"
1313
+ # Get results of all the redirects.
1314
+ http_codes=$( echo "$response" | awk '$1 ~ /^HTTP/ {print $2}' )
1315
+ # Allow intermediate 301 redirects and tolerate proxy-injected 200s
1316
+ broken_redirects=$( echo "$http_codes" | sed '$d' | grep -vE '^(301|200)$' )
1317
+ # The response may end without final code 2xx/4xx/5xx somehow, e.g. network restrictions on www.bing.com causes redirecting to bing.com fails with connection refused.
1318
+ # In this case it should not exclude the last.
1319
+ last_http_code=$( echo "$http_codes" | tail -n 1 )
1320
+ if ! [[ $last_http_code =~ ^(2|4|5)[0-9][0-9]$ ]]; then
1321
+ broken_redirects=$( echo "$http_codes" | grep -vE '^(301|200)$' )
1322
+ fi
1323
+
1324
+ # All HTTP codes are 301 (Moved Permanently), the redirect link exists.
1325
+ if [[ -z "$broken_redirects" ]]; then
1326
+ aka_ms_download_link=$( echo "$response" | awk '$1 ~ /^Location/{print $2}' | tail -1 | tr -d '\r')
1327
+
1328
+ if [[ -z "$aka_ms_download_link" ]]; then
1329
+ say_verbose "The aka.ms link '$aka_ms_link' is not valid: failed to get redirect location."
1330
+ return 1
1331
+ fi
1332
+
1333
+ say_verbose "The redirect location retrieved: '$aka_ms_download_link'."
1334
+ return 0
1335
+ else
1336
+ say_verbose "The aka.ms link '$aka_ms_link' is not valid: received HTTP code: $(echo "$broken_redirects" | paste -sd "," -)."
1337
+ return 1
1338
+ fi
1339
+ }
1340
+
1341
+ get_feeds_to_use()
1342
+ {
1343
+ feeds=(
1344
+ "https://builds.dotnet.microsoft.com/dotnet"
1345
+ "https://ci.dot.net/public"
1346
+ )
1347
+
1348
+ if [[ -n "$azure_feed" ]]; then
1349
+ feeds=("$azure_feed")
1350
+ fi
1351
+
1352
+ if [[ -n "$uncached_feed" ]]; then
1353
+ feeds=("$uncached_feed")
1354
+ fi
1355
+ }
1356
+
1357
+ # THIS FUNCTION MAY EXIT (if the determined version is already installed).
1358
+ generate_download_links() {
1359
+
1360
+ download_links=()
1361
+ specific_versions=()
1362
+ effective_versions=()
1363
+ link_types=()
1364
+
1365
+ # If generate_akams_links returns false, no fallback to old links. Just terminate.
1366
+ # This function may also 'exit' (if the determined version is already installed).
1367
+ generate_akams_links || return
1368
+
1369
+ # Check other feeds only if we haven't been able to find an aka.ms link.
1370
+ if [[ "${#download_links[@]}" -lt 1 ]]; then
1371
+ for feed in ${feeds[@]}
1372
+ do
1373
+ # generate_regular_links may also 'exit' (if the determined version is already installed).
1374
+ generate_regular_links $feed || return
1375
+ done
1376
+ fi
1377
+
1378
+ if [[ "${#download_links[@]}" -eq 0 ]]; then
1379
+ say_err "Failed to resolve the exact version number."
1380
+ return 1
1381
+ fi
1382
+
1383
+ say_verbose "Generated ${#download_links[@]} links."
1384
+ for link_index in ${!download_links[@]}
1385
+ do
1386
+ say_verbose "Link $link_index: ${link_types[$link_index]}, ${effective_versions[$link_index]}, ${download_links[$link_index]}"
1387
+ done
1388
+ }
1389
+
1390
+ # THIS FUNCTION MAY EXIT (if the determined version is already installed).
1391
+ generate_akams_links() {
1392
+ local valid_aka_ms_link=true;
1393
+
1394
+ normalized_version="$(to_lowercase "$version")"
1395
+ if [[ "$normalized_version" != "latest" ]] && [ -n "$normalized_quality" ]; then
1396
+ say_err "Quality and Version options are not allowed to be specified simultaneously. See https://learn.microsoft.com/dotnet/core/tools/dotnet-install-script#options for details."
1397
+ return 1
1398
+ fi
1399
+
1400
+ if [[ -n "$json_file" || "$normalized_version" != "latest" ]]; then
1401
+ # aka.ms links are not needed when exact version is specified via command or json file
1402
+ return
1403
+ fi
1404
+
1405
+ get_download_link_from_aka_ms || valid_aka_ms_link=false
1406
+
1407
+ if [[ "$valid_aka_ms_link" == true ]]; then
1408
+ say_verbose "Retrieved primary payload URL from aka.ms link: '$aka_ms_download_link'."
1409
+ say_verbose "Downloading using legacy url will not be attempted."
1410
+
1411
+ download_link=$aka_ms_download_link
1412
+
1413
+ #get version from the path
1414
+ IFS='/'
1415
+ read -ra pathElems <<< "$download_link"
1416
+ count=${#pathElems[@]}
1417
+ specific_version="${pathElems[count-2]}"
1418
+ unset IFS;
1419
+ say_verbose "Version: '$specific_version'."
1420
+
1421
+ #Retrieve effective version
1422
+ effective_version="$(get_specific_product_version "$azure_feed" "$specific_version" "$download_link")"
1423
+
1424
+ # Add link info to arrays
1425
+ download_links+=($download_link)
1426
+ specific_versions+=($specific_version)
1427
+ effective_versions+=($effective_version)
1428
+ link_types+=("aka.ms")
1429
+
1430
+ # Check if the SDK version is already installed.
1431
+ if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
1432
+ say "$asset_name with version '$effective_version' is already installed."
1433
+ exit 0
1434
+ fi
1435
+
1436
+ return 0
1437
+ fi
1438
+
1439
+ # if quality is specified - exit with error - there is no fallback approach
1440
+ if [ ! -z "$normalized_quality" ]; then
1441
+ say_err "Failed to locate the latest version in the channel '$normalized_channel' with '$normalized_quality' quality for '$normalized_product', os: '$normalized_os', architecture: '$normalized_architecture'."
1442
+ say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support."
1443
+ return 1
1444
+ fi
1445
+ say_verbose "Falling back to latest.version file approach."
1446
+ }
1447
+
1448
+ # THIS FUNCTION MAY EXIT (if the determined version is already installed)
1449
+ # args:
1450
+ # feed - $1
1451
+ generate_regular_links() {
1452
+ local feed="$1"
1453
+ local valid_legacy_download_link=true
1454
+
1455
+ specific_version=$(get_specific_version_from_version "$feed" "$channel" "$normalized_architecture" "$version" "$json_file") || specific_version='0'
1456
+
1457
+ if [[ "$specific_version" == '0' ]]; then
1458
+ say_verbose "Failed to resolve the specific version number using feed '$feed'"
1459
+ return
1460
+ fi
1461
+
1462
+ effective_version="$(get_specific_product_version "$feed" "$specific_version")"
1463
+ say_verbose "specific_version=$specific_version"
1464
+
1465
+ download_link="$(construct_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version" "$normalized_os")"
1466
+ say_verbose "Constructed primary named payload URL: $download_link"
1467
+
1468
+ # Add link info to arrays
1469
+ download_links+=($download_link)
1470
+ specific_versions+=($specific_version)
1471
+ effective_versions+=($effective_version)
1472
+ link_types+=("primary")
1473
+
1474
+ legacy_download_link="$(construct_legacy_download_link "$feed" "$channel" "$normalized_architecture" "$specific_version")" || valid_legacy_download_link=false
1475
+
1476
+ if [ "$valid_legacy_download_link" = true ]; then
1477
+ say_verbose "Constructed legacy named payload URL: $legacy_download_link"
1478
+
1479
+ download_links+=($legacy_download_link)
1480
+ specific_versions+=($specific_version)
1481
+ effective_versions+=($effective_version)
1482
+ link_types+=("legacy")
1483
+ else
1484
+ legacy_download_link=""
1485
+ say_verbose "Could not construct a legacy_download_link; omitting..."
1486
+ fi
1487
+
1488
+ # Check if the SDK version is already installed.
1489
+ if [[ "$dry_run" != true ]] && is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
1490
+ say "$asset_name with version '$effective_version' is already installed."
1491
+ exit 0
1492
+ fi
1493
+ }
1494
+
1495
+ print_dry_run() {
1496
+
1497
+ say "Payload URLs:"
1498
+
1499
+ for link_index in "${!download_links[@]}"
1500
+ do
1501
+ say "URL #$link_index - ${link_types[$link_index]}: ${download_links[$link_index]}"
1502
+ done
1503
+
1504
+ resolved_version=${specific_versions[0]}
1505
+ repeatable_command="./$script_name --version "\""$resolved_version"\"" --install-dir "\""$install_root"\"" --architecture "\""$normalized_architecture"\"" --os "\""$normalized_os"\"""
1506
+
1507
+ if [ ! -z "$normalized_quality" ]; then
1508
+ repeatable_command+=" --quality "\""$normalized_quality"\"""
1509
+ fi
1510
+
1511
+ if [[ "$runtime" == "dotnet" ]]; then
1512
+ repeatable_command+=" --runtime "\""dotnet"\"""
1513
+ elif [[ "$runtime" == "aspnetcore" ]]; then
1514
+ repeatable_command+=" --runtime "\""aspnetcore"\"""
1515
+ fi
1516
+
1517
+ repeatable_command+="$non_dynamic_parameters"
1518
+
1519
+ if [ -n "$feed_credential" ]; then
1520
+ repeatable_command+=" --feed-credential "\""<feed_credential>"\"""
1521
+ fi
1522
+
1523
+ say "Repeatable invocation: $repeatable_command"
1524
+ }
1525
+
1526
+ calculate_vars() {
1527
+ eval $invocation
1528
+
1529
+ script_name=$(basename "$0")
1530
+ normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
1531
+ say_verbose "Normalized architecture: '$normalized_architecture'."
1532
+ normalized_os="$(get_normalized_os "$user_defined_os")"
1533
+ say_verbose "Normalized OS: '$normalized_os'."
1534
+ normalized_quality="$(get_normalized_quality "$quality")"
1535
+ say_verbose "Normalized quality: '$normalized_quality'."
1536
+ normalized_channel="$(get_normalized_channel "$channel")"
1537
+ say_verbose "Normalized channel: '$normalized_channel'."
1538
+ normalized_product="$(get_normalized_product "$runtime")"
1539
+ say_verbose "Normalized product: '$normalized_product'."
1540
+ install_root="$(resolve_installation_path "$install_dir")"
1541
+ say_verbose "InstallRoot: '$install_root'."
1542
+
1543
+ normalized_architecture="$(get_normalized_architecture_for_specific_sdk_version "$version" "$normalized_channel" "$normalized_architecture")"
1544
+
1545
+ if [[ "$runtime" == "dotnet" ]]; then
1546
+ asset_relative_path="shared/Microsoft.NETCore.App"
1547
+ asset_name=".NET Core Runtime"
1548
+ elif [[ "$runtime" == "aspnetcore" ]]; then
1549
+ asset_relative_path="shared/Microsoft.AspNetCore.App"
1550
+ asset_name="ASP.NET Core Runtime"
1551
+ elif [ -z "$runtime" ]; then
1552
+ asset_relative_path="sdk"
1553
+ asset_name=".NET Core SDK"
1554
+ fi
1555
+
1556
+ get_feeds_to_use
1557
+ }
1558
+
1559
+ install_dotnet() {
1560
+ eval $invocation
1561
+ local download_failed=false
1562
+ local download_completed=false
1563
+ local remote_file_size=0
1564
+
1565
+ mkdir -p "$install_root"
1566
+ zip_path="${zip_path:-$(mktemp "$temporary_file_template")}"
1567
+ say_verbose "Archive path: $zip_path"
1568
+
1569
+ for link_index in "${!download_links[@]}"
1570
+ do
1571
+ download_link="${download_links[$link_index]}"
1572
+ specific_version="${specific_versions[$link_index]}"
1573
+ effective_version="${effective_versions[$link_index]}"
1574
+ link_type="${link_types[$link_index]}"
1575
+
1576
+ say "Attempting to download using $link_type link $download_link"
1577
+
1578
+ # The download function will set variables $http_code and $download_error_msg in case of failure.
1579
+ download_failed=false
1580
+ download "$download_link" "$zip_path" 2>&1 || download_failed=true
1581
+
1582
+ if [ "$download_failed" = true ]; then
1583
+ case ${http_code-} in
1584
+ 404)
1585
+ say "The resource at $link_type link '$download_link' is not available."
1586
+ ;;
1587
+ *)
1588
+ say "Failed to download $link_type link '$download_link': ${http_code-} ${download_error_msg-}"
1589
+ ;;
1590
+ esac
1591
+ rm -f "$zip_path" 2>&1 && say_verbose "Temporary archive file $zip_path was removed"
1592
+ else
1593
+ download_completed=true
1594
+ break
1595
+ fi
1596
+ done
1597
+
1598
+ if [[ "$download_completed" == false ]]; then
1599
+ say_err "Could not find \`$asset_name\` with version = $specific_version"
1600
+ say_err "Refer to: https://aka.ms/dotnet-os-lifecycle for information on .NET Core support"
1601
+ return 1
1602
+ fi
1603
+
1604
+ remote_file_size="$(get_remote_file_size "$download_link")"
1605
+
1606
+ say "Extracting archive from $download_link"
1607
+ extract_dotnet_package "$zip_path" "$install_root" "$remote_file_size" || return 1
1608
+
1609
+ # Check if the SDK version is installed; if not, fail the installation.
1610
+ # if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
1611
+ if [[ $specific_version == *"rtm"* || $specific_version == *"servicing"* ]]; then
1612
+ IFS='-'
1613
+ read -ra verArr <<< "$specific_version"
1614
+ release_version="${verArr[0]}"
1615
+ unset IFS;
1616
+ say_verbose "Checking installation: version = $release_version"
1617
+ if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$release_version"; then
1618
+ say "Installed version is $effective_version"
1619
+ return 0
1620
+ fi
1621
+ fi
1622
+
1623
+ # Check if the standard SDK version is installed.
1624
+ say_verbose "Checking installation: version = $effective_version"
1625
+ if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$effective_version"; then
1626
+ say "Installed version is $effective_version"
1627
+ return 0
1628
+ fi
1629
+
1630
+ # Version verification failed. More likely something is wrong either with the downloaded content or with the verification algorithm.
1631
+ say_err "Failed to verify the version of installed \`$asset_name\`.\nInstallation source: $download_link.\nInstallation location: $install_root.\nReport the bug at https://github.com/dotnet/install-scripts/issues."
1632
+ say_err "\`$asset_name\` with version = $effective_version failed to install with an error."
1633
+ return 1
1634
+ }
1635
+
1636
+ args=("$@")
1637
+
1638
+ local_version_file_relative_path="/.version"
1639
+ bin_folder_relative_path=""
1640
+ temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX"
1641
+
1642
+ channel="LTS"
1643
+ version="Latest"
1644
+ json_file=""
1645
+ install_dir="<auto>"
1646
+ architecture="<auto>"
1647
+ dry_run=false
1648
+ no_path=false
1649
+ azure_feed=""
1650
+ uncached_feed=""
1651
+ feed_credential=""
1652
+ verbose=false
1653
+ runtime=""
1654
+ runtime_id=""
1655
+ quality=""
1656
+ internal=false
1657
+ override_non_versioned_files=true
1658
+ non_dynamic_parameters=""
1659
+ user_defined_os=""
1660
+
1661
+ while [ $# -ne 0 ]
1662
+ do
1663
+ name="$1"
1664
+ case "$name" in
1665
+ -c|--channel|-[Cc]hannel)
1666
+ shift
1667
+ channel="$1"
1668
+ ;;
1669
+ -v|--version|-[Vv]ersion)
1670
+ shift
1671
+ version="$1"
1672
+ ;;
1673
+ -q|--quality|-[Qq]uality)
1674
+ shift
1675
+ quality="$1"
1676
+ ;;
1677
+ --internal|-[Ii]nternal)
1678
+ internal=true
1679
+ non_dynamic_parameters+=" $name"
1680
+ ;;
1681
+ -i|--install-dir|-[Ii]nstall[Dd]ir)
1682
+ shift
1683
+ install_dir="$1"
1684
+ ;;
1685
+ --arch|--architecture|-[Aa]rch|-[Aa]rchitecture)
1686
+ shift
1687
+ architecture="$1"
1688
+ ;;
1689
+ --os|-[Oo][SS])
1690
+ shift
1691
+ user_defined_os="$1"
1692
+ ;;
1693
+ --shared-runtime|-[Ss]hared[Rr]untime)
1694
+ say_warning "The --shared-runtime flag is obsolete and may be removed in a future version of this script. The recommended usage is to specify '--runtime dotnet'."
1695
+ if [ -z "$runtime" ]; then
1696
+ runtime="dotnet"
1697
+ fi
1698
+ ;;
1699
+ --runtime|-[Rr]untime)
1700
+ shift
1701
+ runtime="$1"
1702
+ if [[ "$runtime" != "dotnet" ]] && [[ "$runtime" != "aspnetcore" ]]; then
1703
+ say_err "Unsupported value for --runtime: '$1'. Valid values are 'dotnet' and 'aspnetcore'."
1704
+ if [[ "$runtime" == "windowsdesktop" ]]; then
1705
+ say_err "WindowsDesktop archives are manufactured for Windows platforms only."
1706
+ fi
1707
+ exit 1
1708
+ fi
1709
+ ;;
1710
+ --dry-run|-[Dd]ry[Rr]un)
1711
+ dry_run=true
1712
+ ;;
1713
+ --no-path|-[Nn]o[Pp]ath)
1714
+ no_path=true
1715
+ non_dynamic_parameters+=" $name"
1716
+ ;;
1717
+ --verbose|-[Vv]erbose)
1718
+ verbose=true
1719
+ non_dynamic_parameters+=" $name"
1720
+ ;;
1721
+ --azure-feed|-[Aa]zure[Ff]eed)
1722
+ shift
1723
+ azure_feed="$1"
1724
+ non_dynamic_parameters+=" $name "\""$1"\"""
1725
+ ;;
1726
+ --uncached-feed|-[Uu]ncached[Ff]eed)
1727
+ shift
1728
+ uncached_feed="$1"
1729
+ non_dynamic_parameters+=" $name "\""$1"\"""
1730
+ ;;
1731
+ --feed-credential|-[Ff]eed[Cc]redential)
1732
+ shift
1733
+ feed_credential="$1"
1734
+ #feed_credential should start with "?", for it to be added to the end of the link.
1735
+ #adding "?" at the beginning of the feed_credential if needed.
1736
+ [[ -z "$(echo $feed_credential)" ]] || [[ $feed_credential == \?* ]] || feed_credential="?$feed_credential"
1737
+ ;;
1738
+ --runtime-id|-[Rr]untime[Ii]d)
1739
+ shift
1740
+ runtime_id="$1"
1741
+ non_dynamic_parameters+=" $name "\""$1"\"""
1742
+ say_warning "Use of --runtime-id is obsolete and should be limited to the versions below 2.1. To override architecture, use --architecture option instead. To override OS, use --os option instead."
1743
+ ;;
1744
+ --jsonfile|-[Jj][Ss]on[Ff]ile)
1745
+ shift
1746
+ json_file="$1"
1747
+ ;;
1748
+ --skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
1749
+ override_non_versioned_files=false
1750
+ non_dynamic_parameters+=" $name"
1751
+ ;;
1752
+ --keep-zip|-[Kk]eep[Zz]ip)
1753
+ keep_zip=true
1754
+ non_dynamic_parameters+=" $name"
1755
+ ;;
1756
+ --zip-path|-[Zz]ip[Pp]ath)
1757
+ shift
1758
+ zip_path="$1"
1759
+ ;;
1760
+ -?|--?|-h|--help|-[Hh]elp)
1761
+ script_name="dotnet-install.sh"
1762
+ echo ".NET Tools Installer"
1763
+ echo "Usage:"
1764
+ echo " # Install a .NET SDK of a given Quality from a given Channel"
1765
+ echo " $script_name [-c|--channel <CHANNEL>] [-q|--quality <QUALITY>]"
1766
+ echo " # Install a .NET SDK of a specific public version"
1767
+ echo " $script_name [-v|--version <VERSION>]"
1768
+ echo " $script_name -h|-?|--help"
1769
+ echo ""
1770
+ echo "$script_name is a simple command line interface for obtaining dotnet cli."
1771
+ echo " Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
1772
+ echo " - The SDK needs to be installed without user interaction and without admin rights."
1773
+ echo " - The SDK installation doesn't need to persist across multiple CI runs."
1774
+ echo " To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer."
1775
+ echo ""
1776
+ echo "Options:"
1777
+ echo " -c,--channel <CHANNEL> Download from the channel specified, Defaults to \`$channel\`."
1778
+ echo " -Channel"
1779
+ echo " Possible values:"
1780
+ echo " - STS - the most recent Standard Term Support release"
1781
+ echo " - LTS - the most recent Long Term Support release"
1782
+ echo " - 2-part version in a format A.B - represents a specific release"
1783
+ echo " examples: 2.0; 1.0"
1784
+ echo " - 3-part version in a format A.B.Cxx - represents a specific SDK release"
1785
+ echo " examples: 5.0.1xx, 5.0.2xx."
1786
+ echo " Supported since 5.0 release"
1787
+ echo " Warning: Value 'Current' is deprecated for the Channel parameter. Use 'STS' instead."
1788
+ echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used."
1789
+ echo " -v,--version <VERSION> Use specific VERSION, Defaults to \`$version\`."
1790
+ echo " -Version"
1791
+ echo " Possible values:"
1792
+ echo " - latest - the latest build on specific channel"
1793
+ echo " - 3-part version in a format A.B.C - represents specific version of build"
1794
+ echo " examples: 2.0.0-preview2-006120; 1.1.0"
1795
+ echo " -q,--quality <quality> Download the latest build of specified quality in the channel."
1796
+ echo " -Quality"
1797
+ echo " The possible values are: daily, preview, GA."
1798
+ echo " Works only in combination with channel. Not applicable for STS and LTS channels and will be ignored if those channels are used."
1799
+ echo " Supported since 5.0 release."
1800
+ echo " Note: The version parameter overrides the channel parameter when any version other than 'latest' is used, and therefore overrides the quality."
1801
+ echo " --internal,-Internal Download internal builds. Requires providing credentials via --feed-credential parameter."
1802
+ echo " --feed-credential <FEEDCREDENTIAL> Token to access Azure feed. Used as a query string to append to the Azure feed."
1803
+ echo " -FeedCredential This parameter typically is not specified."
1804
+ echo " -i,--install-dir <DIR> Install under specified location (see Install Location below)"
1805
+ echo " -InstallDir"
1806
+ echo " --architecture <ARCHITECTURE> Architecture of dotnet binaries to be installed, Defaults to \`$architecture\`."
1807
+ echo " --arch,-Architecture,-Arch"
1808
+ echo " Possible values: x64, arm, arm64, s390x, ppc64le and loongarch64"
1809
+ echo " --os <system> Specifies operating system to be used when selecting the installer."
1810
+ echo " Overrides the OS determination approach used by the script. Supported values: osx, linux, linux-musl, freebsd, rhel.6."
1811
+ echo " In case any other value is provided, the platform will be determined by the script based on machine configuration."
1812
+ echo " Not supported for legacy links. Use --runtime-id to specify platform for legacy links."
1813
+ echo " Refer to: https://aka.ms/dotnet-os-lifecycle for more information."
1814
+ echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
1815
+ echo " -Runtime"
1816
+ echo " Possible values:"
1817
+ echo " - dotnet - the Microsoft.NETCore.App shared runtime"
1818
+ echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
1819
+ echo " --dry-run,-DryRun Do not perform installation. Display download link."
1820
+ echo " --no-path, -NoPath Do not set PATH for the current process."
1821
+ echo " --verbose,-Verbose Display diagnostics information."
1822
+ echo " --azure-feed,-AzureFeed For internal use only."
1823
+ echo " Allows using a different storage to download SDK archives from."
1824
+ echo " --uncached-feed,-UncachedFeed For internal use only."
1825
+ echo " Allows using a different storage to download SDK archives from."
1826
+ echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
1827
+ echo " -SkipNonVersionedFiles"
1828
+ echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
1829
+ echo " Note: global.json must have a value for 'SDK:Version'"
1830
+ echo " --keep-zip,-KeepZip If set, downloaded file is kept."
1831
+ echo " --zip-path, -ZipPath If set, downloaded file is stored at the specified path."
1832
+ echo " -?,--?,-h,--help,-Help Shows this help message"
1833
+ echo ""
1834
+ echo "Install Location:"
1835
+ echo " Location is chosen in following order:"
1836
+ echo " - --install-dir option"
1837
+ echo " - Environmental variable DOTNET_INSTALL_DIR"
1838
+ echo " - $HOME/.dotnet"
1839
+ exit 0
1840
+ ;;
1841
+ *)
1842
+ say_err "Unknown argument \`$name\`"
1843
+ exit 1
1844
+ ;;
1845
+ esac
1846
+
1847
+ shift
1848
+ done
1849
+
1850
+ say_verbose "Note that the intended use of this script is for Continuous Integration (CI) scenarios, where:"
1851
+ say_verbose "- The SDK needs to be installed without user interaction and without admin rights."
1852
+ say_verbose "- The SDK installation doesn't need to persist across multiple CI runs."
1853
+ say_verbose "To set up a development environment or to run apps, use installers rather than this script. Visit https://dotnet.microsoft.com/download to get the installer.\n"
1854
+
1855
+ if [ "$internal" = true ] && [ -z "$(echo $feed_credential)" ]; then
1856
+ message="Provide credentials via --feed-credential parameter."
1857
+ if [ "$dry_run" = true ]; then
1858
+ say_warning "$message"
1859
+ else
1860
+ say_err "$message"
1861
+ exit 1
1862
+ fi
1863
+ fi
1864
+
1865
+ check_min_reqs
1866
+ calculate_vars
1867
+ # generate_regular_links call below will 'exit' if the determined version is already installed.
1868
+ generate_download_links
1869
+
1870
+ if [[ "$dry_run" = true ]]; then
1871
+ print_dry_run
1872
+ exit 0
1873
+ fi
1874
+
1875
+ install_dotnet
1876
+
1877
+ bin_path="$(get_absolute_path "$(combine_paths "$install_root" "$bin_folder_relative_path")")"
1878
+ if [ "$no_path" = false ]; then
1879
+ say "Adding to current process PATH: \`$bin_path\`. Note: This change will be visible only when sourcing script."
1880
+ export PATH="$bin_path":"$PATH"
1881
+ else
1882
+ say "Binaries of dotnet can be found in $bin_path"
1883
+ fi
1884
+
1885
+ say "Note that the script does not resolve dependencies during installation."
1886
+ say "To check the list of dependencies, go to https://learn.microsoft.com/dotnet/core/install, select your operating system and check the \"Dependencies\" section."
1887
+ say "Installation finished successfully."