Commits

Anton Tayanovskyy committed 01ff3b0

Alternative locking implementation with wait timeout.

Comments (0)

Files changed (2)

BuildMagic.nuspec

 <package>
   <metadata>
     <id>BuildMagic</id>
-    <version>0.0.1</version>
+    <version>0.0.2</version>
     <authors>IntelliFactory</authors>
     <owners>IntelliFactory</owners>
     <licenseUrl>http://www.gnu.org/licenses/agpl-3.0.html</licenseUrl>

BuildMagic.targets

     <BuildMagicNuGetUrl Condition="'$(BuildMagicNuGetUrl)' == ''">http://nuget.org/api/v1/package/NuGet.CommandLine/$(BuildMagicNuGetVersion)</BuildMagicNuGetUrl>
     <BuildMagicNuGetFolder Condition="'$(BuildMagicNuGetFolder)' == ''">$(MSBuildThisFileDirectory)/bin</BuildMagicNuGetFolder>
     <BuildMagicNuGetLocation Condition="'$(BuildMagicNuGetLocation)' == ''">$(BuildMagicNuGetFolder)/NuGet.exe</BuildMagicNuGetLocation>
-    <BuildMagicLock Condition="'$(BuildMagicLock)' == ''">$(MSBuildThisFileDirectory)/BuildMagic.lock</BuildMagicLock>
     <BuildMagicPackagesConfig Condition="'$(BuildMagicPackagesConfig)' == ''">$(MSBuildProjectDirectory)/packages.config</BuildMagicPackagesConfig>
     <BuildMagicSources Condition="'$(BuildMagicSources)' == ''"></BuildMagicSources>
     <BuildMagicPackages Condition="'$(BuildMagicPackages)' == ''">$(MSBuildThisFileDirectory)/../packages</BuildMagicPackages>
   <UsingTask TaskName="BuildMagicDownloadAndExtract" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)/Microsoft.Build.Tasks.v4.0.dll" >
     <ParameterGroup>
       <Address ParameterType="System.String" Required="true" />
-      <ZipFile ParameterType="System.String" Required="true" />
-      <PathInZipFile ParameterType="System.String" Required="true" />
       <DestinationFile ParameterType="System.String" Required="true" />
-      <LockFile ParameterType="System.String" Required="true" />
     </ParameterGroup>
     <Task>
       <Reference Include="WindowsBase" />
+      <Using Namespace="System.IO"/>
+      <Using Namespace="System.IO.Packaging"/>
+      <Using Namespace="System.Net"/>
       <Using Namespace="System.Threading"/>
       <Code Type="Fragment" Language="cs">
         <![CDATA[
-          var locked = false;
-          while (File.Exists(LockFile)) {
-            locked = true;
-            Thread.Sleep(500);
-          }
-          if (locked) return true;
+            var dir = Path.GetDirectoryName(DestinationFile);
+            var lockFile = Path.Combine(dir, "BuildMagic.lock");
+            var waits = 0;
+            Directory.CreateDirectory(dir);
 
-          try {
-            File.WriteAllText(LockFile, "");
-            using (var client = new System.Net.WebClient())
+            // Wait to acquire file system lock.
+            while (true)
             {
-              Directory.CreateDirectory(Path.GetDirectoryName(ZipFile));
-              client.DownloadFile(Address, ZipFile);
+                try
+                {
+                    using (var file = File.Open(lockFile, FileMode.Create, FileAccess.Write, FileShare.None))
+                    {
+                        // Skip if already downloaded.
+                        if (!File.Exists(DestinationFile))
+                        {
+                            var zipFile = Path.GetTempFileName();
+                            using (var client = new WebClient())
+                            {
+                                client.DownloadFile(Address, zipFile);
+                            }
+                            using (var pkg = ZipPackage.Open(zipFile, FileMode.Open))
+                            {
+                                var part = pkg.GetParts().First(x => x.Uri.ToString() == "/tools/NuGet.exe");
+                                using (var stream = part.GetStream(FileMode.Open))
+                                {
+                                    using (var output = File.Open(DestinationFile, FileMode.Create))
+                                    {
+                                        stream.CopyTo(output);
+                                    }
+                                }
+                            }
+                        }
+                        return true;
+                    }
+                }
+                catch (IOException e)
+                {
+                    waits = waits + 1;
+                    if (waits <= 100) {
+                        Thread.Sleep(100);
+                    } else {
+                        this.Log.LogErrorFromException(e);
+                        return false;
+                    }
+                }
             }
-            using (var pkg = System.IO.Packaging.ZipPackage.Open(ZipFile, FileMode.Open))
-            {
-              var part = pkg.GetParts().First(x => x.Uri.ToString() == PathInZipFile);
-              using (var stream = part.GetStream(FileMode.Open))
-              {
-                Directory.CreateDirectory(Path.GetDirectoryName(DestinationFile));
-                using (var output = File.Open(DestinationFile, FileMode.Create))
-                {
-                  stream.CopyTo(output);
-                }
-              }
-              return true;
-            }
-          } finally {
-            File.Delete(LockFile);
-          }
         ]]>
       </Code>
     </Task>
   </UsingTask>
 
   <Target Name="BuildMagicInstallNuget" Condition="!Exists($(BuildMagicNuGetLocation))">
-    <PropertyGroup>
-      <BuildMagicNuGetZip>$(BuildMagicNuGetLocation).zip</BuildMagicNuGetZip>
-    </PropertyGroup>
-    <BuildMagicDownloadAndExtract Address="$(BuildMagicNuGetUrl)" ZipFile="$(BuildMagicNuGetZip)" PathInZipFile="/tools/NuGet.exe" DestinationFile="$(BuildMagicNuGetLocation)" LockFile="$(BuildMagicLock)"/>
+    <BuildMagicDownloadAndExtract Address="$(BuildMagicNuGetUrl)" DestinationFile="$(BuildMagicNuGetLocation)" />
   </Target>
 
   <Target Name="BuildMagicRestore" Condition="Exists('$(BuildMagicPackagesConfig)')" DependsOnTargets="BuildMagicInstallNuget">