|
3 | 3 | #tool "nuget:?package=GitVersion.CommandLine&version=5.12.0" |
4 | 4 | #tool "nuget:?package=NuGet.CommandLine&version=7.0.1" |
5 | 5 |
|
| 6 | +#addin "nuget:?package=LibGit2Sharp&version=0.31.0" |
| 7 | + |
6 | 8 | //------------------------------------------------------------- |
7 | 9 |
|
8 | 10 | public class GeneralContext : BuildContextWithItemsBase |
@@ -76,58 +78,167 @@ public class VersionContext : BuildContextBase |
76 | 78 | var gitVersionSettings = new GitVersionSettings |
77 | 79 | { |
78 | 80 | UpdateAssemblyInfo = false, |
79 | | - Verbosity = GitVersionVerbosity.Verbose |
| 81 | + Verbosity = GitVersionVerbosity.Verbose, |
| 82 | + NoFetch = true |
80 | 83 | }; |
81 | 84 |
|
82 | | - var gitDirectory = ".git"; |
83 | | - if (!CakeContext.DirectoryExists(gitDirectory)) |
| 85 | + var mutexName = $"Global\\Cake_GitVersion_Clone_{generalContext.Solution.Name}"; |
| 86 | + |
| 87 | + CakeContext.Information("Trying to acquire mutex to determine version"); |
| 88 | + |
| 89 | + using (var mutex = new System.Threading.Mutex(false, mutexName, out var createdNew)) |
84 | 90 | { |
85 | | - CakeContext.Information("No local .git directory found, treating as dynamic repository"); |
| 91 | + if (!mutex.WaitOne(TimeSpan.FromMinutes(2))) |
| 92 | + { |
| 93 | + throw new Exception("Could not acquire mutex to determine version"); |
| 94 | + } |
86 | 95 |
|
87 | | - // Make a *BIG* assumption that the solution name == repository name |
88 | | - var repositoryName = generalContext.Solution.Name; |
89 | | - var dynamicRepositoryPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), repositoryName); |
| 96 | + CakeContext.Information("Mutex acquired"); |
90 | 97 |
|
91 | | - if (ClearCache) |
| 98 | + var gitDirectory = ".git"; |
| 99 | + if (!CakeContext.DirectoryExists(gitDirectory)) |
92 | 100 | { |
93 | | - CakeContext.Warning("Cleaning the cloned temp directory, disable by setting 'GitVersion_ClearCache' to 'false'"); |
94 | | - |
| 101 | + CakeContext.Information("No local .git directory found, treating as dynamic repository"); |
| 102 | + |
| 103 | + // Make a *BIG* assumption that the solution name == repository name |
| 104 | + var repositoryName = generalContext.Solution.Name; |
| 105 | + var dynamicRepositoryPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), repositoryName); |
| 106 | + |
| 107 | + // Note: for now we fully clear the cache each time until we found a solid way to pull the latest changes |
| 108 | + var clearCache = ClearCache || true; |
| 109 | + if (clearCache) |
| 110 | + { |
| 111 | + CakeContext.Warning("Cleaning the cloned temp directory, disable by setting 'GitVersion_ClearCache' to 'false'"); |
| 112 | + |
| 113 | + if (CakeContext.DirectoryExists(dynamicRepositoryPath)) |
| 114 | + { |
| 115 | + CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings |
| 116 | + { |
| 117 | + Force = true, |
| 118 | + Recursive = true |
| 119 | + }); |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + // Validate first |
| 124 | + if (string.IsNullOrWhiteSpace(generalContext.Repository.BranchName)) |
| 125 | + { |
| 126 | + throw new Exception("No local .git directory was found, but repository branch was not specified either. Make sure to specify the branch"); |
| 127 | + } |
| 128 | + |
| 129 | + if (string.IsNullOrWhiteSpace(generalContext.Repository.Url)) |
| 130 | + { |
| 131 | + throw new Exception("No local .git directory was found, but repository url was not specified either. Make sure to specify the branch"); |
| 132 | + } |
| 133 | + |
| 134 | + CakeContext.Information($"Fetching dynamic repository from url '{generalContext.Repository.Url}' => '{dynamicRepositoryPath}'"); |
| 135 | + |
| 136 | + // Note: starting with GitVersion 6.x, we need to handle dynamic repos ourselves, |
| 137 | + // and we will be using Cake.Git and LibGit2Sharp directly to support cloning a specific commit id |
| 138 | + |
| 139 | + var existingRepository = false; |
95 | 140 | if (CakeContext.DirectoryExists(dynamicRepositoryPath)) |
96 | 141 | { |
97 | | - CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings |
| 142 | + CakeContext.Information("Dynamic repository directory already exists"); |
| 143 | + |
| 144 | + if (CakeContext.GitIsValidRepository(dynamicRepositoryPath)) |
98 | 145 | { |
99 | | - Force = true, |
100 | | - Recursive = true |
101 | | - }); |
| 146 | + CakeContext.Information("Dynamic repository already exists, reusing existing clone"); |
| 147 | + existingRepository = true; |
| 148 | + } |
| 149 | + else |
| 150 | + { |
| 151 | + CakeContext.Information("Dynamic repository already exists but is not valid, recloning"); |
| 152 | + |
| 153 | + CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings |
| 154 | + { |
| 155 | + Force = true, |
| 156 | + Recursive = true |
| 157 | + }); |
| 158 | + } |
102 | 159 | } |
103 | | - } |
104 | 160 |
|
105 | | - // Validate first |
106 | | - if (string.IsNullOrWhiteSpace(generalContext.Repository.BranchName)) |
107 | | - { |
108 | | - throw new Exception("No local .git directory was found, but repository branch was not specified either. Make sure to specify the branch"); |
109 | | - } |
| 161 | + if (existingRepository) |
| 162 | + { |
| 163 | + // TODO: How to pull? |
| 164 | + } |
| 165 | + else |
| 166 | + { |
| 167 | + var gitCloneSettings = new GitCloneSettings |
| 168 | + { |
| 169 | + BranchName = generalContext.Repository.BranchName, |
| 170 | + Checkout = true, |
| 171 | + IsBare = false, |
| 172 | + RecurseSubmodules = false, |
| 173 | + }; |
| 174 | + |
| 175 | + if (!string.IsNullOrWhiteSpace(generalContext.Repository.Username) && |
| 176 | + !string.IsNullOrWhiteSpace(generalContext.Repository.Password)) |
| 177 | + { |
| 178 | + CakeContext.Information("Cloning with authentication"); |
| 179 | + |
| 180 | + CakeContext.GitClone(generalContext.Repository.Url, |
| 181 | + dynamicRepositoryPath, |
| 182 | + generalContext.Repository.Username, |
| 183 | + generalContext.Repository.Password, |
| 184 | + gitCloneSettings); |
| 185 | + } |
| 186 | + else |
| 187 | + { |
| 188 | + CakeContext.Information("Cloning without authentication"); |
110 | 189 |
|
111 | | - if (string.IsNullOrWhiteSpace(generalContext.Repository.Url)) |
112 | | - { |
113 | | - throw new Exception("No local .git directory was found, but repository url was not specified either. Make sure to specify the branch"); |
| 190 | + CakeContext.GitClone(generalContext.Repository.Url, |
| 191 | + dynamicRepositoryPath, |
| 192 | + gitCloneSettings); |
| 193 | + } |
| 194 | + } |
| 195 | + |
| 196 | + //LibGit2Sharp.Repository.Clone(generalContext.Repository.Url, dynamicRepositoryPath, cloneOptions); |
| 197 | + |
| 198 | + if (!CakeContext.GitIsValidRepository(dynamicRepositoryPath)) |
| 199 | + { |
| 200 | + throw new Exception($"Cloned repository at '{dynamicRepositoryPath}' is not a valid repository"); |
| 201 | + } |
| 202 | + |
| 203 | + CakeContext.Information("Ensuring correct commit ID"); |
| 204 | + |
| 205 | + // According to docs, to not get into a detached head state, we need to: |
| 206 | + // |
| 207 | + // git checkout -B 'branch' 'commit id' |
| 208 | + // |
| 209 | + // This seems impossible via Cake.Git (and LibGit2Sharp directly), so we will |
| 210 | + // just invoke git.exe directly here |
| 211 | + // |
| 212 | + //CakeContext.GitCheckout(dynamicRepositoryPath, generalContext.Repository.CommitId); |
| 213 | + |
| 214 | + var gitCommit = CakeContext.GitLogTip(dynamicRepositoryPath); |
| 215 | + if (!string.Equals(gitCommit.Sha, generalContext.Repository.CommitId, StringComparison.OrdinalIgnoreCase)) |
| 216 | + { |
| 217 | + var gitExe = CakeContext.Tools.Resolve("git.exe").FullPath; |
| 218 | + |
| 219 | + using (var process = CakeContext.StartAndReturnProcess(gitExe, |
| 220 | + new ProcessSettings |
| 221 | + { |
| 222 | + WorkingDirectory = dynamicRepositoryPath, |
| 223 | + Arguments = $"checkout -B {generalContext.Repository.BranchName} {generalContext.Repository.CommitId}", |
| 224 | + })) |
| 225 | + { |
| 226 | + process.WaitForExit(); |
| 227 | + |
| 228 | + // This should output 0 as valid arguments supplied |
| 229 | + CakeContext.Information("Exit code: {0}", process.GetExitCode()); |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + CakeContext.Information("Preparing GitVersion settings"); |
| 234 | + |
| 235 | + gitVersionSettings.WorkingDirectory = dynamicRepositoryPath; |
114 | 236 | } |
115 | 237 |
|
116 | | - CakeContext.Information($"Fetching dynamic repository from url '{generalContext.Repository.Url}' => '{dynamicRepositoryPath}'"); |
117 | | - |
118 | | - // Dynamic repository |
119 | | - gitVersionSettings.UserName = generalContext.Repository.Username; |
120 | | - gitVersionSettings.Password = generalContext.Repository.Password; |
121 | | - gitVersionSettings.Url = generalContext.Repository.Url; |
122 | | - gitVersionSettings.Branch = generalContext.Repository.BranchName; |
123 | | - gitVersionSettings.Commit = generalContext.Repository.CommitId; |
124 | | - gitVersionSettings.NoFetch = false; |
125 | | - gitVersionSettings.WorkingDirectory = generalContext.RootDirectory; |
126 | | - gitVersionSettings.DynamicRepositoryPath = dynamicRepositoryPath; |
127 | | - gitVersionSettings.Verbosity = GitVersionVerbosity.Verbose; |
128 | | - } |
| 238 | + CakeContext.Information("Running GitVersion"); |
129 | 239 |
|
130 | | - _gitVersionContext = CakeContext.GitVersion(gitVersionSettings); |
| 240 | + _gitVersionContext = CakeContext.GitVersion(gitVersionSettings); |
| 241 | + } |
131 | 242 | } |
132 | 243 |
|
133 | 244 | return _gitVersionContext; |
|
0 commit comments