e27d3003c3a33f3be96a348420b5b49e6773dfb7
[teamcity/dotNetPackagesSupport.git] / nuget-extensions / nuget-runner / src / NuGetRunner.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.IO;\r
4 using System.Reflection;\r
5 using System.Linq;\r
6 \r
7 namespace JetBrains.TeamCity.NuGetRunner\r
8 {\r
9   public class NuGetRunner\r
10   {\r
11     private readonly string myNuGetExe;\r
12     private readonly Assembly myNuGetAssembly;\r
13     private readonly List<EventHandler> myStartEvents = new List<EventHandler>();\r
14     private readonly List<EventHandler> myFinishEvents = new List<EventHandler>();\r
15 \r
16     public NuGetRunner(string NuGetExe)\r
17     {\r
18       myNuGetExe = NuGetExe;\r
19       if (!File.Exists(NuGetExe))\r
20         throw new NuGetLoadException("Failed to find NuGet.exe at " + myNuGetExe);\r
21 \r
22       try\r
23       {\r
24         myNuGetAssembly = Assembly.LoadFrom(myNuGetExe);\r
25       }\r
26       catch (Exception e)\r
27       {\r
28         throw new NuGetLoadException("Failed to load NuGet assembly into AppDomain. " + e.Message, e);\r
29       }\r
30 \r
31       NuGetExtensionsPath = new Lazy<string>(LocateNuGetExtensionsPath);\r
32     }\r
33 \r
34     private string LocateNuGetExtensionsPath()\r
35     {\r
36       var mi = myNuGetAssembly.EntryPoint.DeclaringType;\r
37       foreach (\r
38         var type in\r
39           new Func<Type>[] {() => mi.DeclaringType, () => myNuGetAssembly.GetType("NuGet.Program")}.Select(Compute).\r
40             Where(x => x != null))\r
41       {\r
42         var field = type.GetField("ExtensionsDirectoryRoot",\r
43                                   BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);\r
44         if (field != null && field.FieldType == typeof (string))\r
45         {\r
46           var extensionsPath = field.GetValue(null) as string;\r
47           if (extensionsPath != null)\r
48             return extensionsPath;\r
49         }\r
50       }\r
51       //This is explicit path value taken from NuGet source code\r
52       return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "NuGet", "Commands");\r
53     }\r
54 \r
55     public Lazy<string> NuGetExtensionsPath { get; private set; }\r
56 \r
57     public event EventHandler BeforeNuGetStarted { add { myStartEvents.Add(value); } remove { myStartEvents.Remove(value);  } }\r
58     public event EventHandler AfterNuGetFinished { add { myFinishEvents.Add(value); } remove { myFinishEvents.Remove(value); } }\r
59 \r
60     private void CallEvents(IEnumerable<EventHandler> handler)\r
61     {\r
62       foreach (var h in handler)\r
63       {\r
64         try\r
65         {\r
66           h(this, EventArgs.Empty);\r
67         } catch (Exception e)\r
68         {\r
69           Console.Error.WriteLine("Failed to execute event: " + e);\r
70         }\r
71       }\r
72     }\r
73 \r
74     public int Run(string[] argz)\r
75     {\r
76       CallEvents(myStartEvents);\r
77 \r
78       try\r
79       {\r
80         var result = myNuGetAssembly.EntryPoint.Invoke(null, new[] {argz});\r
81 \r
82         if (result is int)\r
83           return (int) result;\r
84 \r
85         return 0;\r
86       } finally\r
87       {\r
88         CallEvents(myFinishEvents);\r
89       }\r
90     }\r
91 \r
92     private static T Compute<T>(Func<T> func) where T : class\r
93     {\r
94       try\r
95       {\r
96         return func();\r
97       }\r
98       catch\r
99       {\r
100         return null;\r
101       }\r
102     }\r
103   }\r
104 }