|
7 | 7 | using System.Net; |
8 | 8 | using System.Runtime.InteropServices; |
9 | 9 | using System.Text; |
10 | | -using WebDriverManager.Helpers; |
11 | 10 |
|
12 | 11 | namespace WebDriverManager.Services.Impl |
13 | 12 | { |
14 | 13 | public class BinaryService : IBinaryService |
15 | 14 | { |
16 | 15 | public IWebProxy Proxy { get; set; } |
17 | 16 |
|
| 17 | + [Obsolete("binaryName parameter is redundant, use SetupBinary(url, zipDestination, binDestination)")] |
18 | 18 | public string SetupBinary(string url, string zipDestination, string binDestination, string binaryName) |
19 | 19 | { |
20 | | - if (File.Exists(binDestination)) return binDestination; |
21 | | - FileHelper.CreateDestinationDirectory(zipDestination); |
22 | | - zipDestination = DownloadZip(url, zipDestination); |
23 | | - FileHelper.CreateDestinationDirectory(binDestination); |
| 20 | + return SetupBinary(url, zipDestination, binDestination); |
| 21 | + } |
| 22 | + |
| 23 | + public string SetupBinary(string url, string zipPath, string binaryPath) |
| 24 | + { |
| 25 | + var zipDir = Path.GetDirectoryName(zipPath); |
| 26 | + var binaryDir = Path.GetDirectoryName(binaryPath); |
| 27 | + var binaryName = Path.GetFileName(binaryPath); |
| 28 | + |
| 29 | + // |
| 30 | + // If the destination already exists, we don't have to do anything |
| 31 | + // |
| 32 | + if (Directory.Exists(binaryDir)) return binaryPath; |
| 33 | + |
| 34 | + // |
| 35 | + // Download the driver |
| 36 | + // |
| 37 | + Directory.CreateDirectory(zipDir); |
| 38 | + zipPath = DownloadZip(url, zipPath); |
| 39 | + |
| 40 | + // |
| 41 | + // Copy or extract binary(s) into a staging directory |
| 42 | + // |
| 43 | + var stagingDir = Path.Combine(zipDir, "staging"); |
| 44 | + var stagingPath = Path.Combine(stagingDir, binaryName); |
| 45 | + |
| 46 | + Directory.CreateDirectory(stagingDir); |
24 | 47 |
|
25 | | - if (zipDestination.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) |
| 48 | + if (zipPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) |
26 | 49 | { |
27 | | - File.Copy(zipDestination, binDestination); |
| 50 | + File.Copy(zipPath, stagingPath); |
28 | 51 | } |
29 | | - else if (zipDestination.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) |
| 52 | + else if (zipPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) |
30 | 53 | { |
31 | | - UnZip(zipDestination, binDestination, binaryName); |
| 54 | + UnZip(zipPath, stagingPath, binaryName); |
32 | 55 | } |
33 | | - else if (zipDestination.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase)) |
| 56 | + else if (zipPath.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase)) |
34 | 57 | { |
35 | | - UnZipTgz(zipDestination, binDestination); |
| 58 | + UnZipTgz(zipPath, stagingPath); |
36 | 59 | } |
37 | 60 |
|
38 | 61 | #if NETSTANDARD |
39 | | - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || |
40 | | - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) |
| 62 | + var needsChmod = |
| 63 | + RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || |
| 64 | + RuntimeInformation.IsOSPlatform(OSPlatform.OSX); |
| 65 | + |
| 66 | + if (needsChmod) |
41 | 67 | { |
42 | | - var chmod = Process.Start("chmod", $"+x {binDestination}"); |
| 68 | + var chmod = Process.Start("chmod", $"+x {stagingPath}"); |
43 | 69 | chmod?.WaitForExit(); |
44 | 70 | } |
45 | 71 | #endif |
46 | 72 |
|
47 | | - RemoveZip(zipDestination); |
48 | | - return binDestination; |
| 73 | + // |
| 74 | + // Create the destination parent directory if it doesn't exist |
| 75 | + // |
| 76 | + var binaryParentDir = Path.GetDirectoryName(binaryDir); |
| 77 | + Directory.CreateDirectory(binaryParentDir); |
| 78 | + |
| 79 | + // |
| 80 | + // Atomically rename the staging directory to the destination directory |
| 81 | + // |
| 82 | + // If a parallel thread or process races us and wins, the destination will already exist and this will fail |
| 83 | + // with an IOException. |
| 84 | + // |
| 85 | + Exception renameException = null; |
| 86 | + try |
| 87 | + { |
| 88 | + Directory.Move(stagingDir, binaryDir); |
| 89 | + } |
| 90 | + catch (Exception ex) |
| 91 | + { |
| 92 | + renameException = ex; |
| 93 | + } |
| 94 | + |
| 95 | + // |
| 96 | + // Regardless of what happens, do a best-effort clean up |
| 97 | + // |
| 98 | + try |
| 99 | + { |
| 100 | + if (Directory.Exists(stagingDir)) Directory.Delete(stagingDir, true); |
| 101 | + } |
| 102 | + catch (Exception ex) |
| 103 | + { |
| 104 | + Console.Error.WriteLine(ex.ToString()); |
| 105 | + } |
| 106 | + try |
| 107 | + { |
| 108 | + RemoveZip(zipPath); |
| 109 | + } |
| 110 | + catch (Exception ex) |
| 111 | + { |
| 112 | + Console.Error.WriteLine(ex.ToString()); |
| 113 | + } |
| 114 | + |
| 115 | + // |
| 116 | + // If the destination still doesn't exist, it means the rename failed in an unexpected way |
| 117 | + // |
| 118 | + if (!Directory.Exists(binaryDir)) |
| 119 | + { |
| 120 | + throw new Exception($"Error writing {binaryDir}", renameException); |
| 121 | + } |
| 122 | + |
| 123 | + return binaryPath; |
49 | 124 | } |
50 | 125 |
|
51 | 126 | public string DownloadZip(string url, string destination) |
|
0 commit comments