Ajax Minifier Manifest Task with clobber

Jun 21, 2013 at 4:32 PM
I'm having some issues using the -clobber argument in and xml file using Ajax Minifier Manifest Task. I've got it all working so that it minifies all of the files defined in my ajaxmin xml file when the project is built. But I have run into an issue when checking the minfied files into TFS. When checking them into TFS they are marked as read only which then means that I get an error when building the project. I've tried adding <arguments>-clobber</arguments> in my ajaxmin xml file but that isn't working.

So, I tried creating a bat file and using the exe to minify the files. It works for simple input output files but when I try and pass the ajaxmin xml file I get an exception being thrown.

How can I get it so that clobber will work when using an ajaxmin xml file either through the manifest task (ideally) or the command line?

Here is the output from the exe
C:\ISDDEV2-DL\Web\Development\Isd.Web_13.5.2_Checkout\Website\OnlineShop\Common\
CC\CSS\Core>"C:\Program Files (x86)\Microsoft\Microsoft Ajax Minifier\AjaxMin.ex
e" -css -xml css.xml

Unhandled Exception: System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "Microsoft.Ajax.Minifier.Tasks.ManifestStrings.resources" was correctly embedded or linked into assembly "AjaxMinifier" at compile time, or that all the satellite assemblies required are loadable and fully signed.   
at System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String fileName)
   at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
   at Microsoft.Ajax.Utilities.Configuration.ManifestStrings.get_InputFileNotFound()
   at Microsoft.Ajax.Utilities.ManifestUtilities.ValidateAndNormalize(Manifest manifest, String inputFolder, String outputFolder, Boolean throwInputErrors)
   at Microsoft.Ajax.Utilities.MainClass.ProcessXmlFile(String xmlPath, String outputFolder)
   at Microsoft.Ajax.Utilities.MainClass.Run()
   at Microsoft.Ajax.Utilities.MainClass.Main(String[] args)
   at Microsoft.Ajax.Utilities.Stub.Program.Main(String[] args)
The contents of my ajaxmin xml file is
<?xml version="1.0" encoding="utf-8" ?>
<root>
    <!-- Bundles -->
    <output path="..\Common\CC\CSS\Core\global.min.css">
        <input path="Common\CC\CSS\Core\Framework-Local.css"/>
        <input path="Common\CC\CSS\Core\AddToBasket.css"/>
        <input path="Common\CC\CSS\Core\Checkout\Address.css"/>
        <input path="Common\CC\CSS\Core\Checkout\BasketSummary.css"/>
        <input path="Common\CC\CSS\Core\Checkout\CreateAccount.css"/>
        <input path="Common\CC\CSS\Core\Checkout\Login.css"/>
        <input path="Common\CC\CSS\Core\Checkout\OrderConfirmation.css"/>
        <input path="Common\CC\CSS\Core\Checkout\OrderReceipt.css"/>
        <input path="Common\CC\CSS\Core\Checkout\PromotionalCodes.css"/>
        <input path="Common\CC\CSS\Core\Checkout\StepIndicator.css"/>
    </output>
    <!-- Files -->
    <output path="..\Common\CC\CSS\Core\Framework-Local.min.css">
        <input path="Common\CC\CSS\Core\Framework-Local.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\AddToBasket.min.css">
        <input path="Common\CC\CSS\Core\AddToBasket.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\Address.min.css">
        <input path="Common\CC\CSS\Core\Checkout\Address.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\BasketSummary.min.css">
        <input path="Common\CC\CSS\Core\Checkout\BasketSummary.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\CreateAccount.min.css">
        <input path="Common\CC\CSS\Core\Checkout\CreateAccount.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\Login.min.css">
        <input path="Common\CC\CSS\Core\Checkout\Login.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\OrderConfirmation.min.css">
        <input path="Common\CC\CSS\Core\Checkout\OrderConfirmation.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\OrderReceipt.min.css">
        <input path="Common\CC\CSS\Core\Checkout\OrderReceipt.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\PromotionalCodes.min.css">
        <input path="Common\CC\CSS\Core\Checkout\PromotionalCodes.css"/>
    </output>
    <output path="..\Common\CC\CSS\Core\Checkout\StepIndicator.min.css">
        <input path="Common\CC\CSS\Core\Checkout\StepIndicator.css"/>
    </output>
</root>
Coordinator
Jun 23, 2013 at 5:01 PM
That's because the -clobber switch is purposely not supported by the build task. It's extremely dangerous and should not be used in project builds. It would just overwrite a checked-in file, which won't check it out or anything, so I personally don't think that is the proper way to go. We at MSN do not check minified files into our TFS project -- those are the products of the build, just as the DLLs and EXEs are. Surely you don't check your compiled binaries into TFS too, right? Why would you want to check the results of your build into your source tree?
Jun 23, 2013 at 5:08 PM
Thanks for the reply. TBH the main reason that I checked the minified files into the project was that the project output gets copied to another location after the build and when the minifed files weren't part of the project they weren't copied over. I just wanted a quick and dirty way to get them copied over to prove that the minification will work because it isn't used where I work at the moment. I've gone back to not having them checked in to TFS now and I'll just have to get the guy that wrote the build jobs to add in a step to copy the minified files too.

However, that still doesn't fix the issue in using the ajaxmin xml from the command line. I would still like to know how to do this as it's handy to know anyway.
Coordinator
Jun 23, 2013 at 7:43 PM
Ack -- sorry, I didn't notice the exception. Yes, I can repro this -- but it's weird because I have ManifestStrings.resx in the EXE's project and as part of the neutral culture. It should work just fine, but it's not. I'll dig into it.

In the meantime, from the stack trace it looks like it's trying to tell you that an input file doesn't exist:
at Microsoft.Ajax.Utilities.Configuration.ManifestStrings.get_InputFileNotFound()
Unfortunately, without the proper message text, you can't tell which file doesn't exist. Try looking at each file listed in the manifest to see if one of them doesn't exist, and either remove the reference from the manifest or put the optional="true" attribute on it. But most likely it's a path thing -- I believe when using the command-line, relative paths are from the location of the manifest file.
Coordinator
Jun 23, 2013 at 8:23 PM
Ugh - namespace set improperly on the RESX file in question for all the projects. I'll have that fixed in 4.95. Thanks for finding that.
Coordinator
Jun 25, 2013 at 4:28 PM
Okay, release 4.95 is out. Please give it a try; the exception should be gone now and a valid "input file not found" message should be shown telling you the file in question. I still think it's probably a relative-path root folder issue introduced by the switch from build task to command-line. Keep in mind that when using the EXE, relative paths in the manifest are relative to the manifest file itself.

Also, if only files in your project get copied to another location, can't you add the files to your project without adding them to TFS? That way the files are technically in your project, but they won't be marked read-only, won't need to be checked out, etc. Would that help you with that issue?
Jun 25, 2013 at 4:53 PM
Thanks for the quick replies. I'm not using the EXE any more because the only reason I wanted that to work was to get around the files not being copied from the build as previously discussed.

In terms of not adding the files into TFS, are you saying I should add them to the project file but not check the minified files in to TFS?
Coordinator
Jun 25, 2013 at 5:02 PM
Yes, it's possible to add a file to the project but not check it into source control (that's how I handle the private key I use to sign the AjaxMin binaries -- I don't distribute it, so it's not in TFS, but it's still part of my project). If you do a "tfpt scorch" on your project, the files will get deleted because they aren't in TFS. The files in the Solution Explorer will have a little "broken" icon next to them indicating that they don't exist. But when you build, the build process will create them and everything will be good. If your copy process is looking only at files in your project, you should be good to go. Since they aren't in TFS, they won't be marked as read-only, so building will easily overwrite them.
Jun 25, 2013 at 5:23 PM
I'll give that a bash and see how I get on. If that doesn't work I don't think it will be a big job to modify the build job to copy the minified files anyway. Everything is fine locally, it's only an issue with the build job so I think I will modify that to look for and copy minified files. We already do something similar for other file types although they are copied into the root of the site, not the folder they originate from.

Thanks for your help though!