implement nuget list function with service messages support
authorEugene.Petrenko <eugene.petrenko@gmail.com>
Wed, 13 Jul 2011 18:13:13 +0000 (22:13 +0400)
committerEugene.Petrenko <eugene.petrenko@gmail.com>
Wed, 13 Jul 2011 18:13:13 +0000 (22:13 +0400)
nuget-extensions/nuget-commands/nuget-commands.csproj
nuget-extensions/nuget-commands/src/NuGetTeamCityListCommand.cs
nuget-extensions/nuget-commands/src/Util/ServiceMessageFormatter.cs [new file with mode: 0644]
nuget-extensions/nuget-commands/src/Util/ServiceMessageProperty.cs [new file with mode: 0644]
nuget-extensions/nuget-tests/nuget-tests.csproj
nuget-extensions/nuget-tests/src/NuGetRunner.cs [new file with mode: 0644]
nuget-extensions/nuget-tests/src/NuGetRunnerTest.cs
nuget-extensions/nuget-tests/src/NuGetRunner_ListCommandTest.cs [new file with mode: 0644]

index 8701210a0bc203b92826278f998d043906b8f911..c73b19f9abc1f6e4f95a462c4595aba4f6638cdc 100644 (file)
@@ -35,6 +35,7 @@
       <HintPath>..\lib\nuget\1.4\NuGet.exe</HintPath>\r
     </Reference>\r
     <Reference Include="System" />\r
+    <Reference Include="System.ComponentModel.Composition" />\r
     <Reference Include="System.Core" />\r
     <Reference Include="System.Xml.Linq" />\r
     <Reference Include="System.Data.DataSetExtensions" />\r
@@ -46,6 +47,8 @@
     <Compile Include="src\NuGetTeamCityListCommand.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
     <Compile Include="src\NuGetTeamCityPingCommand.cs" />\r
+    <Compile Include="src\Util\ServiceMessageFormatter.cs" />\r
+    <Compile Include="src\Util\ServiceMessageProperty.cs" />\r
   </ItemGroup>\r
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
index 973fe094c752f2e2a03f3ecf0209f9051c49f234..8282710894f464c101f181e214115d3c9cc96c3f 100644 (file)
@@ -1,16 +1,27 @@
-using System.Collections.Generic;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel.Composition;\r
+using System.Linq;\r
+using System.Linq.Expressions;\r
+using JetBrains.TeamCity.NuGet.ExtendedCommands.Util;\r
 using NuGet;\r
 using NuGet.Commands;\r
+using NuGet.Common;\r
+using PackageSourceProviderExtensions = NuGet.Common.PackageSourceProviderExtensions;\r
 \r
 namespace JetBrains.TeamCity.NuGet.ExtendedCommands\r
 {\r
   [Command("TeamCity.List", "Lists packages for given Id with parsable output")]\r
   public class NuGetTeamCityListCommand : Command\r
   {\r
-    private readonly List<string> mySources = new List<string>();\r
+    [Import]\r
+    public IPackageRepositoryFactory RepositoryFactory { get; set; }\r
 \r
-    [Option("Sources to search for package", AltName = "s")]\r
-    public ICollection<string> Source { get { return mySources; } }\r
+    [Import]\r
+    public IPackageSourceProvider SourceProvider { get; set; }\r
+\r
+    [Option("NuGet package Source to search for package")]\r
+    public String Source { get; set; }\r
 \r
     [Option("Package Id to check for version update")]\r
     public string Id { get; set; }\r
@@ -21,9 +32,35 @@ namespace JetBrains.TeamCity.NuGet.ExtendedCommands
     public override void ExecuteCommand()\r
     {\r
       System.Console.Out.WriteLine("TeamCity NuGet List command.");\r
-      System.Console.Out.WriteLine("Sources: {0}", string.Join(", ", mySources.ToArray()));\r
+      System.Console.Out.WriteLine("Source: {0}", Source ?? "<null>");\r
       System.Console.Out.WriteLine("Package Id: {0}", Id ?? "<null>");\r
       System.Console.Out.WriteLine("Version: {0}", Version ?? "<null>");\r
+      \r
+      System.Console.Out.WriteLine("Checking for latest version...");\r
+      var packages = GetPackages();\r
+      foreach (var p in packages)\r
+      {\r
+        var msg = ServiceMessageFormatter.FormatMessage(\r
+          "nuget-package",\r
+          new ServiceMessageProperty("Id", p.Id),\r
+          new ServiceMessageProperty("Version", p.Version.ToString())          \r
+          );\r
+\r
+        System.Console.Out.WriteLine(msg);\r
+      }\r
+    }\r
+\r
+    private IEnumerable<IPackage> GetPackages()\r
+    {\r
+      IPackageRepository packageRepository = RepositoryFactory.CreateRepository(Source);\r
+\r
+      Expression<Func<IPackage, bool>> exp = p => p.Id == Id;\r
+      IQueryable<IPackage> packages = packageRepository\r
+        .GetPackages()\r
+        .Where(exp);\r
+\r
+      if (Version == null) return packages;\r
+      return packages.Where(VersionUtility.ParseVersionSpec(Version).ToDelegate());\r
     }\r
   }\r
 }\r
diff --git a/nuget-extensions/nuget-commands/src/Util/ServiceMessageFormatter.cs b/nuget-extensions/nuget-commands/src/Util/ServiceMessageFormatter.cs
new file mode 100644 (file)
index 0000000..8084cb5
--- /dev/null
@@ -0,0 +1,82 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+\r
+namespace JetBrains.TeamCity.NuGet.ExtendedCommands.Util\r
+{\r
+  public static class ServiceMessageFormatter\r
+  {\r
+    private static readonly Pair[] ESCAPINGS = {\r
+                                                 new Pair('|', "||"), \r
+                                                 new Pair('\'', "|'"), \r
+                                                 new Pair('\n', "|n"), \r
+                                                 new Pair('\r', "|r"), \r
+                                                 new Pair(']', "|]")\r
+                                               };\r
+\r
+    private const string SERVICE_MESSAGE_HEADER = "##teamcity[";\r
+\r
+    /// <summary>\r
+    /// Performs TeamCity-format escaping of a string.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    private static string Escape(string value)\r
+    {\r
+      return ESCAPINGS.Aggregate(value, (current, pair) => current.Replace(pair.What, pair.Replacement));\r
+    }\r
+\r
+    private struct Pair\r
+    {\r
+      public readonly string What;\r
+      public readonly string Replacement;\r
+\r
+      private Pair(string what, string replacement)\r
+      {\r
+        What = what;\r
+        Replacement = replacement;\r
+      }\r
+\r
+      public Pair(char what, string replacement)\r
+        : this(what.ToString(), replacement)\r
+      {\r
+      }\r
+    }\r
+\r
+    public static string FormatMessage(string sMessageName, string sValue)\r
+    {\r
+      if (string.IsNullOrEmpty(sMessageName))\r
+        throw new ArgumentNullException("sMessageName");\r
+      if (sValue == null)\r
+        throw new ArgumentNullException("sValue");\r
+\r
+      if (Escape(sMessageName) != sMessageName)\r
+        throw new ArgumentException("The message name contains illegal characters.", "sMessageName");\r
+\r
+      return string.Format("{2}{0} '{1}']", sMessageName, Escape(sValue), SERVICE_MESSAGE_HEADER);\r
+    }\r
+\r
+    public static string FormatMessage(string sMessageName, params ServiceMessageProperty[] properties)\r
+    {\r
+      if (string.IsNullOrEmpty(sMessageName))\r
+        throw new ArgumentNullException("sMessageName");\r
+      if (properties == null)\r
+        throw new ArgumentNullException("properties");\r
+\r
+      if (Escape(sMessageName) != sMessageName)\r
+        throw new ArgumentException("The message name contains illegal characters.", "sMessageName");\r
+\r
+      var sb = new StringBuilder();\r
+      sb.AppendFormat("{1}{0}", sMessageName, SERVICE_MESSAGE_HEADER);\r
+      foreach (var property in properties)\r
+      {\r
+        if (Escape(property.Key) != property.Key)\r
+          throw new InvalidOperationException(string.Format("The property name \93{0}\94 contains illegal characters.", property.Key));\r
+        sb.AppendFormat(" {0}='{1}'", property.Key, Escape(property.Value));\r
+      }\r
+      sb.Append(']');\r
+\r
+      return sb.ToString();\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/nuget-extensions/nuget-commands/src/Util/ServiceMessageProperty.cs b/nuget-extensions/nuget-commands/src/Util/ServiceMessageProperty.cs
new file mode 100644 (file)
index 0000000..f109c6c
--- /dev/null
@@ -0,0 +1,14 @@
+namespace JetBrains.TeamCity.NuGet.ExtendedCommands.Util\r
+{\r
+  public struct ServiceMessageProperty\r
+  {\r
+    public readonly string Key;\r
+    public readonly string Value;\r
+\r
+    public ServiceMessageProperty(string key, string value)\r
+    {\r
+      Key = key;\r
+      Value = value;\r
+    }\r
+  }\r
+}
\ No newline at end of file
index f88b905b232d0c5f57beef5a0e3720e48fb63a33..078ae4af81bec7f42fa95fa7691eb2c4a8dc5d9a 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <Compile Include="src\NuGet.cs" />\r
+    <Compile Include="src\NuGetRunner.cs" />\r
     <Compile Include="src\NuGetRunnerTest.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
+    <Compile Include="src\NuGetRunner_ListCommandTest.cs" />\r
     <Compile Include="src\ProcessExecutor.cs" />\r
   </ItemGroup>\r
   <ItemGroup>\r
diff --git a/nuget-extensions/nuget-tests/src/NuGetRunner.cs b/nuget-extensions/nuget-tests/src/NuGetRunner.cs
new file mode 100644 (file)
index 0000000..9159d80
--- /dev/null
@@ -0,0 +1,10 @@
+using System;\r
+using JetBrains.TeamCity.NuGetRunner;\r
+\r
+namespace JetBrains.TeamCity.NuGet.Tests\r
+{\r
+  public static class NuGetRunner\r
+  {\r
+    public static readonly Lazy<string> Path = new Lazy<string>(()=>typeof (Program).Assembly.GetAssemblyPath());\r
+  }\r
+}
\ No newline at end of file
index 4e2301350bba9953f4356d2760b99982464e1fac..438a7dfe4f4c7442017b79d3f3ba6fa842054155 100644 (file)
@@ -1,5 +1,4 @@
 using System;\r
-using JetBrains.TeamCity.NuGetRunner;\r
 using NUnit.Framework;\r
 \r
 namespace JetBrains.TeamCity.NuGet.Tests\r
@@ -7,12 +6,10 @@ namespace JetBrains.TeamCity.NuGet.Tests
   [TestFixture]\r
   public class NuGetRunnerTest\r
   {\r
-    private readonly Lazy<string> myRunnerPath = new Lazy<string>(()=>typeof (Program).Assembly.GetAssemblyPath());\r
-\r
     [Test]\r
     public void TestExcuteNuGet()\r
     {\r
-      var r = ProcessExecutor.ExecuteProcess(myRunnerPath.Value, NuGet.NuGetPath, "help");\r
+      var r = ProcessExecutor.ExecuteProcess(NuGetRunner.Path.Value, NuGet.NuGetPath, "help");\r
       Console.Out.WriteLine(r);\r
 \r
       Assert.IsTrue(r.ExitCode == 0);\r
@@ -21,7 +18,7 @@ namespace JetBrains.TeamCity.NuGet.Tests
     [Test]\r
     public void TestDumpExtensionsPath()\r
     {\r
-      var r = ProcessExecutor.ExecuteProcess(myRunnerPath.Value, NuGet.NuGetPath, "---TeamCity.DumpExtensionsPath");\r
+      var r = ProcessExecutor.ExecuteProcess(NuGetRunner.Path.Value, NuGet.NuGetPath, "---TeamCity.DumpExtensionsPath");\r
       Console.Out.WriteLine(r);\r
 \r
       Assert.IsTrue(r.ExitCode == 0);\r
@@ -30,7 +27,7 @@ namespace JetBrains.TeamCity.NuGet.Tests
     [Test]\r
     public void TestCommand_TeamCityPing()\r
     {\r
-      ProcessExecutor.ExecuteProcess(myRunnerPath.Value, NuGet.NuGetPath, "TeamCity.Ping")\r
+      ProcessExecutor.ExecuteProcess(NuGetRunner.Path.Value, NuGet.NuGetPath, "TeamCity.Ping")\r
         .Dump()\r
         .AssertExitedSuccessfully()\r
         .AssertNoErrorOutput()\r
diff --git a/nuget-extensions/nuget-tests/src/NuGetRunner_ListCommandTest.cs b/nuget-extensions/nuget-tests/src/NuGetRunner_ListCommandTest.cs
new file mode 100644 (file)
index 0000000..6e70e6e
--- /dev/null
@@ -0,0 +1,19 @@
+using NUnit.Framework;\r
+using NuGet;\r
+\r
+namespace JetBrains.TeamCity.NuGet.Tests\r
+{\r
+  [TestFixture]\r
+  public class NuGetRunner_ListCommandTest\r
+  {\r
+    [Test]\r
+    public void TestCommand_TeamListPublic()\r
+    {\r
+      ProcessExecutor.ExecuteProcess(NuGetRunner.Path.Value, NuGet.NuGetPath, "TeamCity.List", "-Id", "NUnit", "-Source", NuGetConstants.DefaultFeedUrl)\r
+        .Dump()\r
+        .AssertExitedSuccessfully()\r
+        .AssertNoErrorOutput()\r
+        .AssertOutputContains("##teamcity[nuget-package Id='NUnit' Version='2.5.10.11092']");\r
+    }\r
+  }\r
+}
\ No newline at end of file