Now it bumps all dependent versions numbers and only after that, it builds all needed projects so that a build error can be fixed and the build be restarted without have inconsistent version numbers.
laptop:~/Projects/active/NugetCracker$ ./nugetcracker NugetCracker 0.6 See https://github.com/monoman/NugetCracker
Using /home/rafael/Projects/active/NugetCracker/MetaProject.NugetCracker Scanning '.' > '/home/rafael/Projects/active/NugetCracker' . Scanned 144 directories Found 2 components Sorting... Finding dependents...
Ready > l Listing all components... [0001] Commons.Prevalence.1.0 - Minimal prevalence support for .NET [C# Nuget Project] [0002] NugetCracker.0.6 - A builder for versioned nugets within a web of dependencies [C# Project]
Ready > help Available Commands: BumpVersion Bumps up a version for a component Help, ? Show this list of commands or an specific command help List List components, optionally filtered by regular expression Quit, Exit Stops interactive mode Rebuild Rebuilds current version for a component
Ready > r Commons Rebuilding component Commons.Prevalence.1.0 XBuild Engine Version 2.11.0.0 Mono, Version 2.11.0.0 Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2011. Build started 9/11/2011 2:13:20 PM. __________________________________________________ Project "/home/rafael/Projects/active/NugetCracker/Commons.Prevalence/Commons.Prevalence.csproj" (default target(s)): Done building project "/home/rafael/Projects/active/NugetCracker/Commons.Prevalence/Commons.Prevalence.csproj". Build succeeded. Time Elapsed 00:00:00.8898590
Ready > r Nug Rebuilding component NugetCracker.0.6 XBuild Engine Version 2.11.0.0 Mono, Version 2.11.0.0 Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2011. Build started 9/11/2011 2:13:46 PM. __________________________________________________ /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. Project "/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj" (default target(s)): /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. /usr/lib/mono/4.0/Microsoft.Common.targets: warning : Found a conflict between : 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Using 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' reference. Done building project "/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj". Build succeeded. Warnings: /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj (default targets) -> /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj (default targets) -> /usr/lib/mono/4.0/Microsoft.Common.targets (ResolveAssemblyReferences target) -> Time Elapsed 00:00:04.7531090
Ready > help bumpversion Usage:
BumpVersion [options] pattern
Bumps up the [AssemblyVersion]/Package Version of the component and rebuilds/repackages. The [AssemblyFileVersion] attribute also is kept in sync with the [AssemblyVersion]. If component generates a Nuget it is not automatically published unless the --cascade or --publish options were specified.
Options -part:major|minor|build|revision|none Increments the major, minor, build, revision version number. If option is ommitted the default is to increment build number. -dontcascade Update all dependent components to use the new build/package, and them their dependent components and so on. If some components generate a Nuget, the Nuget is published to a temporary output 'source' and the dependent components have their package references updated, if all goes successfully packages are them published to the default or specified source. -publish Specifies that package should be published if successful. -to: Specifies source other than the default to publish nugets to.
Ready > b nug Bumping component 'NugetCracker' version from 0.6 to 0.6.1 ==== cascading Setting new version to 0.6.1 Building NugetCracker.0.6.1 XBuild Engine Version 2.11.0.0 Mono, Version 2.11.0.0 Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2011. Build started 9/11/2011 2:15:27 PM. __________________________________________________ /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. Project "/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj" (default target(s)): /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. /usr/lib/mono/4.0/Microsoft.Common.targets: warning : Found a conflict between : 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' and 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Using 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' reference. Done building project "/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj". Build succeeded. Warnings: /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj: warning : Cannot import project '/usr/lib/mono/4.0/Microsoft.CSharp.targets' again. It was already imported by '/home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj'. Ignoring. /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj (default targets) -> /home/rafael/Projects/active/NugetCracker/NugetCracker/NugetCracker.csproj (default targets) -> /usr/lib/mono/4.0/Microsoft.Common.targets (ResolveAssemblyReferences target) -> Time Elapsed 00:00:04.2109010
I approach this with a more systemic view to have something like the MonoMagic App Wall (chose another name because a store would emphasize a commercial offering), with apps that may be easily installable/usable on any of the miriad platforms where Mono/.NET is available, Pinta could just be the forerunner.
Imagine an iPad/Android version of Pinta, with your drawings/photos synced to your personal cloud storage, so that you can take your editing session back at your Linux notebook later...
monoman:~/Projects/NugetCracker$ mono NugetCracker/bin/Debug/NugetCracker.exe -c list NugetCracker 0.4 See https://github.com/monoman/NugetCracker
Using /home/rafael/Projects/active/NugetCracker/MetaProject.NugetCracker Scanning '.' > '/home/rafael/Projects/active/NugetCracker' . Scanned 128 directories Found 2 components Sorting... Listing all components... [0001] Commons.Prevalence.1.0 - Minimal prevalence support for .NET [C# Nuget Project] [0002] NugetCracker.0.4 - A builder for versioned nugets within a web of dependencies [C# Project] Done! monoman:~/Projects/NugetCracker$ mono NugetCracker/bin/Debug/NugetCracker.exe -c bumpversion -part:minor nu NugetCracker 0.4 See https://github.com/monoman/NugetCracker
Using /home/rafael/Projects/active/NugetCracker/MetaProject.NugetCracker Scanning '.' > '/home/rafael/Projects/active/NugetCracker' . Scanned 128 directories Found 2 components Sorting... Bumping component 'NugetCracker' version from 0.4 to 0.5 Setting new version to 0.5 Building NugetCracker.0.5 Done! monoman:~/Projects/NugetCracker$ mono NugetCracker/bin/Debug/NugetCracker.exe -c list NugetCracker 0.5 See https://github.com/monoman/NugetCracker
Using /home/rafael/Projects/active/NugetCracker/MetaProject.NugetCracker Scanning '.' > '/home/rafael/Projects/active/NugetCracker' . Scanned 128 directories Found 2 components Sorting... Listing all components... [0001] Commons.Prevalence.1.0 - Minimal prevalence support for .NET [C# Nuget Project] [0002] NugetCracker.0.5 - A builder for versioned nugets within a web of dependencies [C# Project] Done!
Version 0.4 - BumpVersion now increments version, builds project and packs nuget Uses new color-capable indenting console-logger
Sample session:
NugetCracker 0.4
See https://github.com/monoman/NugetCracker
Using C:\Projects\MetaProject.NugetCracker
Scanning '.' - 'C:\Projects'
..........................
Scanned 6454 directories
Found 36 components
Sorting...
Ready - l inad
Listing components filtered by 'inad' ...
[0001] ManagementPluginAD.2.5.35 - ActiveDirectory Management Plugin [C# Nuget Project]
Ready - help
Available Commands:
BumpVersion Bumps up a version for a component
Help, ? Show this list of commands or an specific command help
List List components, optionally filtered by regular expression
Quit, Exit Stops interactive mode
Ready - help b
Usage:
BumpVersion [options] pattern
Bumps up the [AssemblyVersion]/Package Version of the component and rebuilds/repackages.
The [AssemblyFileVersion] attribute also is kept in sync with the [AssemblyVersion].
If component generates a Nuget it is not automatically published unless the --cascade
or --publish options were specified.
Options
-part:[major, minor, build, revision}
Increments the major, minor, build, revision version number.
If option is ommitted the default is to increment build number.
-cascade
Update all dependent components to use the new build/package, and them their dependent
components and so on. If some components generate a Nuget, the Nuget is published to
a temporary output 'source' and the dependent components have their package references
updated, if all goes successfully packages are them published to the default or specified
source.
-publish
Specifies that even if not cascaded package should be published if successful.
-to:
Specifies source other than the default to publish nugets to.
Ready - b -part:revision inad
Bumping component 'ManagementPluginAD' version from 2.5.35 to 2.5.35.1
Setting new version to 2.5.35.1
Building ManagementPluginAD.2.5.35.1
Packaging ManagementPluginAD.2.5.35.1
Attempting to build package from 'ManagementPluginAD.csproj'.
Packing files from 'C:\Projects\ManagementPluginAD\bin\Debug'.
Using 'ManagementPluginAD.nuspec' for metadata.
Found packages.config. Using packages listed as dependencies
Successfully created package 'C:\Projects\ManagementPluginAD\ManagementPluginAD.2.5.35.1.nupkg'.
Ready -
Using C:\Projects\xxx\MetaProject.NugetCracker Scanning '.' > 'C:\Projects\xxx' .......................... Scanned 6454 directories Found 36 components Sorting... Ready > help Available Commands: BumpVersion Bumps up a version for a component Help Show this list of commands or an specific command help List List components, optionally filtered by regular expression Quit, Exit Stops interactive mode Ready >
Well lately I've been a heavy user of NuGet packaging, trying to tame versioning issues in some proprietary projects I work on that evolve, and partly reuse, near to a hundred libraries (many of them in vertically-dependent sets aligned to 'plugins' in the applications).
Let's put it bluntly: IT'S A NIGHTMARE.
First of all, we have many solutions as it is unfeasible to load and work with a single one containing hundreds of projects.
Also we needed to organize source in a hierarchy of folders, for subsystems, for specific plugin trees, for product, separating test projects, etc... So it means we have tree of folders with projects in leafs, nested 3,4, or more levels down from the solution that uses them.
Finally, we have solutions that share some projects (one of the purposes of adopting NuGet is to avoid this pattern, but we aren't there yet).
Summing up the above points, we are very very far from the NuGet assumption of a single-solution, with all projects nested just one level, and mainly using external NuGets from the standard source feed.
<digression>
The standard NuGet feed is rarely used by us, because most packages there just don't support .NET 2.0, which our projects are still bound to, the sole package we could use from there was log4net, which is stable for some years, The rest we needed to cook our own versions of nugets for Npgsql, nHibernate 1.2, Castle.ActiveRecord 1.0RC3, and so on. All of this is published on a server shared folder, as we doesn't have time allowance to setup a NuGet server
</digression>
Let's just exemplify what all that means...
A contrived and simplified scenario:
Library NugetCracker.Core 1.0.0.0 depends only on framework assemblies.
Library NugetCracker.CLI 1.0.0.0 depends on NugetCracker.Core 1.0.0.0 and framework assemblies
Library NugetCracker.Web 1.0.0.0 depends on NugetCracker.Core 1.0.0.0 and NancyFX and framework assemblies
Program NugetCracker 1.0.0.0 depends on NugetCracker.CLI 1.0.0.0 and NugetCracker.Web 1.0.0.0
Now if we allow the Package Manager to get away with forcing bindingRedirects in the app.config (or web.config), we could publish a new nuget for NugetCracker.Core 1.0.1.0 and update just the NugetCracker program. Now, this may work if the changes are non-breaking, but if, for example, you need to add a new method to some interface in core that the other libraries must implement and the program uses, we will have to update the intermediary nugets, build and publish new nugets, and them update the program.
I think that now you can easily extrapolate that for my real scenario that means many iterations of building/publishing/updating across many solutions.
Well time to fast-forward to what I expect to be able to do when my newest project NugetCracker 1.0 is done:
In the command line:
> NugetCracker
Scanning for solutions in .
Found NugetCracker.sln
-- Project NugetCracker.Core generates nuget for version 1.0.0.0
-- Project NugetCracker.CLI generates nuget for version 1.0.0.0 depends on NugetCracker.Core
-- Project NugetCracker.Web generates nuget for version 1.0.0.0 depends on NugetCracker.Core, NancyFx
-- Project NugetCracker generates program for version 1.0.0.0 depends on NugetCracker.CLI, NugetCracker.Web
No nugets sources specified using default feed
No publishing feed/share specified, publishing to folder .\NugetPackages
Command > BumpVersion --minor --cascade NugetCracker.Core
Bumping version of package NugetCracker.Core to 1.1.0.0
Building NugetCracker.Core
Packaging NugetCracker.Core.1.1
Publishing NugetCracker.Core.1.1 to .\NugetPackages
Updating Package Dependency on NugetCracker.Core to 1.1 in NugetCracker.CLI, NugetCracker.Web
Bumping version of package NugetCracker.CLI to 1.1.0.0
Building NugetCracker.CLI
Packaging NugetCracker.CLI.1.1
Publishing NugetCracker.CLI.1.1 to .\NugetPackages
Bumping version of package NugetCracker.Web to 1.1.0.0
Building NugetCracker.Web
Packaging NugetCracker.Web.1.1
Publishing NugetCracker.Web.1.1 to .\NugetPackages
Updating Package Dependency on NugetCracker.CLI to 1.1 in NugetCracker
Updating Package Dependency on NugetCracker.Web to 1.1 in NugetCracker
Bumping version of program NugetCracker.Core to 1.1.0.0
Building NugetCracker
Packaging .\NugetCracker.1.1.zip for zip installation
Command > PublishTo -Apikey xxxxxxx -Source http://nuget.mycompany.com/
Publishing NugetCracker.Core.1.1 to http://nuget.mycompany.com/
Publishing NugetCracker.CLI.1.1 to http://nuget.mycompany.com/
Publishing NugetCracker.Web.1.1 to http://nuget.mycompany.com/
I've been reading and watching the videos from Google's Campfire One, about the new features they've added to App Engine, specially the Java support, and got thinking of some possibilities when throwing Mono in the picture:
We can see if they have interest in having Mono support in the App Engine, meaning basically to be able to host ASP.NET apps in there. That entails customizing the core libs/APIs using Mono as the VM and the libraries source, and also developing a plugin for Visual Studio (and maybe Monodevelop/Sharpdevelop) to give ASP.NET devs (WebForms and MVC) the same integrated experience they've provided for Java devs using Eclipse
We can help Keerthi's proposal to GSOC for implementing a clone of Azzure take off, and integrate it into Monodevelop, and perhaps Visual Studio. The advantage here being that we would have an open-sourced cloud implementation, that more people can host, even as an in-house solution.
We can retarget the Java in App Engine ideas from Computing in the Cloud, to Computing in the Crowd (Sovereign Computing), it even keeps itself in the Java realm for the Sneer implementation of SC.
Sneer.NET could offer something akin to Azzure
We can drop all but the main concepts and have some Mono-based Cloud Implementation.
Well possibly some other permutations are also viable.
I've just thought to get the ball rolling on discussing those dreamable projects.
I've found some people discussing ways to do that. Someone talked about an alternate undocumented tag to put a reference but it didn't work, but another one really offered me the missing and useful information that the blob there in the xml is just the .ico file in hex form.
Problem is that I wanted to make it an automatic thing: edit the .ico file, build the project and voilá! the new icon shows when you select your rebuilt addin in the test VSNET instance "About" dialog.
So first I've coded this small utility program:
using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text;
namespace IconHexer { class Program { static void Main(string[] args) { try { if (args.Length >= 1) { string icoFile = args[0]; if (File.Exists(icoFile)) { StringBuilder builder = new StringBuilder(); byte[] data = File.ReadAllBytes(icoFile); for (int i = 0; i < data.Length; i++) builder.Append(data[i].ToString("X2")); string hexedIcon = builder.ToString(); if (args.Length < 2) Console.WriteLine(hexedIcon); else for (int j = 1; j < args.Length; j++) { string addinFile = args[j]; if (File.Exists(addinFile)) { string addinBackupFile = addinFile + ".backup"; string xml = File.ReadAllText(addinFile, Encoding.Unicode); int start = xml.IndexOf("<AboutIconData>"); int end = xml.IndexOf("</AboutIconData>"); if (end > start && start > 0) { xml = xml.Substring(0, start + "<AboutIconData>".Length) + hexedIcon + xml.Substring(end); if (File.Exists(addinBackupFile)) File.Delete(addinBackupFile); File.Move(addinFile, addinBackupFile); File.WriteAllText(addinFile, xml, Encoding.Unicode); Console.WriteLine("File '{0}' updated (backuped at '{1}')", addinFile, addinBackupFile); } } else { ShowError("Addin file '{0}' doesn't exist", addinFile); } } } else { ShowError("Icon file '{0}' doesn't exist", icoFile); } } else { ShowError("Please use '{0} pathToIcoFile [pathToAddinFile]'", Path.GetFileName(Assembly.GetEntryAssembly().Location)); } } catch (Exception e) { ShowError(e.ToString()); } }
private static void ShowError(string format, params string[] parameters) { Console.Error.WriteLine("ERROR: " + format, parameters); Environment.ExitCode = 1; } } }
After building it as an exe tool in the solution I've tweaked the csproj for the Addin project to specially mark the two addin files:
<ItemGroup> <Content Include="..\..\..\Addins\NUnitRunnerAddIn - For Testing.AddIn"> <Link>NUnitRunnerAddIn - For Testing.AddIn</Link> <AddinFile>true</AddinFile> </Content> <EmbeddedResource Include="NUnitRunnerAddIn.ico" /> <Content Include="NUnitRunnerAddIn.AddIn"> <AddinFile>true</AddinFile> </Content> </ItemGroup>
Last step is to put a build dependency on the tool project from the addin project, and edit the icon file (which path is hardcoded on the example above) and build the solution and run the addin and as expected the new icon is there in the VSNET about box as promised.
Hope it helps some other guy having to do that in the future...