Example #1
0
        public PackageScript(string filename)
        {
            Event <Verbose> .Raise("PackageScript", "Constructor");

            _sheet = new RootPropertySheet(this);

            // get the full path to the .autopkgFile
            FullPath = filename.GetFullPath();



            // parse the script
            _sheet.ParseFile(filename);


            _sheet.ImportText(_requiredTemplate, "required");

            // temp hack to work around static & ltcg getting marked as used when they are just in the template.
            var scriptText = File.ReadAllText(filename);

            if (scriptText.IndexOf("static", StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _sheet.ImportText(_requiredTemplateStatic, "required_static");
            }

            // end hack
            if (scriptText.IndexOf("ltcg", StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _sheet.ImportText(_requiredTemplateLTCG, "required_ltcg");
            }
            // ensure we have at least the package ID
            var packageName = _sheet.View.nuget.nuspec.id;

            if (string.IsNullOrEmpty(packageName))
            {
                throw new ClrPlusException("the Field nuget.nuspec.id can not be null or empty. You must specify an id for a package.");
            }

            // set the package name macro
            _sheet.AddMacro("pkgname", packageName);
            _sheet.CurrentView.AddMacroHandler((name, context) => _macros.ContainsKey(name.ToLower()) ? _macros[name.ToLower()] : null);
            _sheet.CurrentView.AddMacroHandler((name, context) => System.Environment.GetEnvironmentVariable(name));

            Pivots = new Pivots(_sheet.CurrentView.GetProperty("configurations"));
        }
        internal string Save(bool cleanIntermediateFiles, bool generateOnly, out IEnumerable <string> overlayPackages)
        {
            List <string> overlays        = null;
            string        packageFileName = null;
            // overlays never really happen for overlay packages.
            IEnumerable <string> tmpOverlayPackages;

            // clear out the nuspec files node.
            _nuSpec.files = null;
            var temporaryFiles = new List <string>();

            var files = _nuSpec.Add("files");

            if (PkgRole == PackageRole.@default)
            {
                // default xamlUi
                var xamlText = _defaultUIProperties;
                if (xamlText.Is())
                {
                    var targetFilename = @"default-propertiesui.xml";
                    var xamlPath       = Path.Combine(Directory, targetFilename);
                    xamlPath.TryHardToDelete();
                    File.WriteAllText(xamlPath, xamlText);
                    temporaryFiles.Add(xamlPath);
                    AddFileToNuSpec(xamlPath, @"\build\native\{0}".format(targetFilename));
                    Targets.Value.Xml.AddItemGroup().AddItem("PropertyPageSchema", @"$(MSBuildThisFileDirectory)\{0}".format(targetFilename));
                }

                // generated xaml
                var xaml = GenerateSettingsXaml();
                if (xaml != null)
                {
                    var targetFilename = @"{0}-propertiesui-{1}.xml".format(_pkgName, Guid.NewGuid());
                    var xamlPath       = Path.Combine(Directory, targetFilename);
                    xamlPath.TryHardToDelete();
                    Event <Verbose> .Raise("NugetPackage.Save", "Saving xaml file [{0}].", xamlPath);

                    xaml.Save(xamlPath);
                    temporaryFiles.Add(xamlPath);
                    AddFileToNuSpec(xamlPath, @"\build\native\{0}".format(targetFilename));
                    Targets.Value.Xml.AddItemGroup().AddItem("PropertyPageSchema", @"$(MSBuildThisFileDirectory)\{0}".format(targetFilename));
                }


                // save the /build/configurations.autopkg file
                var configurationsFilename = @"configurations.autopkg";
                var cfgPath = Path.Combine(Directory, configurationsFilename);
                cfgPath.TryHardToDelete();
                SaveConfigurationFile(cfgPath);
                temporaryFiles.Add(cfgPath);
                AddFileToNuSpec(cfgPath, @"\build\{0}".format(configurationsFilename));

                var publisherInfoFilename = @"publisher-info.txt";
                var pifPath = Path.Combine(Directory, publisherInfoFilename);
                pifPath.TryHardToDelete();
                SavePifFile(pifPath);
                temporaryFiles.Add(pifPath);
                AddFileToNuSpec(pifPath, @"\build\{0}".format(publisherInfoFilename));

                string tags = _nuSpec.metadata.tags;
                tags = tags.Replace(",", " ");

                if (tags.IndexOf("nativepackage") == -1)
                {
                    tags = tags + " nativepackage";
                }

                _nuSpec.metadata.tags = tags;


                // always add the msbuild extensions to the main package
                AddFileToNuSpec(Path.Combine(etcPath, "CoApp.NuGetNativeMSBuildTasks.dll.orig"), @"\build\native\private\CoApp.NuGetNativeMSBuildTasks.dll.orig");

                // first, register all the tasks
                foreach (var t in MSBuildExtensionTasks)
                {
                    var usingTask = Targets.Value.Xml.AddUsingTask(t, NuGetPackageOverlayTaskAssembly, null);
                    usingTask.Condition = "'$(DesignTimeBuild)' != 'true' AND ('$(NugetMsBuildExtensionLoaded)' == '' OR '$(NugetMsBuildExtensionLoaded)' == 'false')";
                }


                // 'declare' the  property in props
                var pg   = Props.Value.Xml.AddPropertyGroup();
                var prop = pg.AddProperty("NugetMsBuildExtensionLoaded", "false");
                prop.Condition = "'$(NugetMsBuildExtensionLoaded)' == '' OR '$(NuGet-OverlayLoaded)' == 'false'";

                prop           = pg.AddProperty(NuGetNativeExtensionPath, NuGetNativeExtensionPathValue);
                prop.Condition = NuGetNativeExtensionPathCondition;


                // 'declare' the properties in global scope/
                var propName = "Needs-{0}".format(_pkgName);
                pg.AddProperty(propName, "");
                pg.Condition = "'$({0})' == '' OR '$({0})' == '*Undefined*'".format(propName);

                propName = "Needs-{0}-Version".format(_pkgName);
                pg.AddProperty(propName, "");
                pg.Condition = "'$({0})' == '' OR '$({0})' == '*Undefined*'".format(propName);


                var initTarget = Targets.Value.EarlyInitTarget.Value;
                var copyTask   = initTarget.AddTask("Copy");
                copyTask.SetParameter("SkipUnchangedFiles", "true");
                copyTask.SetParameter("SourceFiles", @"$(NuGet-NativeExtensionPath)\coapp.NuGetNativeMSBuildTasks.dll.orig");
                copyTask.SetParameter("DestinationFiles", @"$(NuGet-NativeExtensionPath)\coapp.NuGetNativeMSBuildTasks.dll");

                pg             = initTarget.AddPropertyGroup();
                prop           = pg.AddProperty("NugetMsBuildExtensionLoaded", "true");
                prop.Condition = "'$(NugetMsBuildExtensionLoaded)' == '' OR '$(NuGet-OverlayLoaded)' == 'false'";

                // then add the NuGetPackageOverlay tasks into the init target
                // var task = Targets.Value.LookupTarget("BeforeBuild").AddTask("CheckRuntimeLibrary");

                // task.SetParameter("RuntimeLibrary", "%(ClCompile.RuntimeLibrary)");
                // task.SetParameter("ExpectedRuntimeLibrary", @"$(ExpectedRuntimeLibrary)");
                // task.SetParameter("LibraryName", SafeName);
                // task.SetParameter("Configuration", "");
            }

            Event <Verbose> .Raise("NugetPackage.Save", "Saving nuget spec file to [{0}].", FullPath);

            // this is where we decide if we're going to split this into overlays or not.
            if (PkgRole == PackageRole.@default && _fileSets.Keys.Count > 1 && _fileSets.Keys.SelectMany(set => _fileSets[set].Values).Sum(srcPath => new FileInfo(srcPath).Length) > SplitThreshold)
            {
                // ok, this package is gonna get split

                // first, add the init target stuff in the .props
                var initTarget = Props.Value.EarlyInitTarget.Value;
                var pg         = initTarget.AddPropertyGroup();

                // version check.
                var wantVer = ((UInt64)((FourPartVersion)(string)_nuSpec.metadata.version)).ToString();

                var nvPropName = "Needs-{0}-Version".format(_pkgName);
                var propName   = "Needs-{0}".format(_pkgName);

                var prop = pg.AddProperty(nvPropName, (string)_nuSpec.metadata.version);
                prop.Condition = "'$({0})' == '' OR $({0}) < {1} ".format(propName, wantVer);

                prop           = pg.AddProperty(propName, wantVer);
                prop.Condition = "'$({0})' == '' OR $({0}) < {1} ".format(propName, wantVer);

                // then add the init target stuff in the .targets

                // now, iterate thru each file set, and create an overlay package for just those files
                // (If the size of a whole file set is less than 100k, we'll just add it to the main package)
                foreach (var set in _fileSets.Keys.Where(each => each.Is()))
                {
                    long setSize = _fileSets[set].Values.Sum(srcPath => new FileInfo(srcPath).Length);
                    if (setSize < (MinimumPivotSize))
                    {
                        foreach (var src in _fileSets[set].Keys)
                        {
                            AddFileToNuSpec(_fileSets[set][src], src);
                        }
                    }
                    else
                    {
                        overlays = overlays ?? new List <string>();

                        var overlayPackageName = "{0}.overlay-{1}".format(_pkgName, Pivots.GetExpressionFilename("", set));

                        // create a seperate package file
                        using (var pkg = new NugetPackage(_packageScript, PackageRole.overlay, overlayPackageName)) {
                            pkg._fileSets.Add(string.Empty, _fileSets[set]);
                            pkg.Process();

                            pkg.Save(cleanIntermediateFiles, generateOnly, out tmpOverlayPackages);

                            // add each overlay package created to the master list of overlays
                            overlays.Add(overlayPackageName);

                            // iterate thru all the files in the base set, and add them to this package's list
                            foreach (var src in _fileSets[string.Empty].Keys)
                            {
                                AddFileToNuSpec(_fileSets[string.Empty][src], src);
                            }

                            // then add the NuGetPackageOverlay tasks into the init target
                            var task = Targets.Value.EarlyInitTarget.Value.AddTask("NuGetPackageOverlay");

                            task.SetParameter("Package", overlayPackageName);
                            task.SetParameter("Version", "$({0})".format(nvPropName));
                            task.SetParameter("PackageDirectory", @"$(MSBuildThisFileDirectory)\..\..");
                            task.SetParameter("SolutionDirectory", @"$(SolutionDir)");

                            // set the condition for the overlay to the appropriate condition pivot.
                            task.Condition = Pivots.GetMSBuildCondition(Targets.Value.Name, set);
                        }
                    }
                }

                if (overlays != null && overlays.Count > 0)
                {
                    // add the two DLLs and the nuget.exe into the package.

                    AddFileToNuSpec(Path.Combine(etcPath, "CoApp.NuGetNativeExtensions.dll"), @"\build\native\private\CoApp.NuGetNativeExtensions.dll");
                    AddFileToNuSpec(Path.Combine(etcPath, "nuget.exe"), @"\build\native\private\nuget.exe");

                    // add the cmd script to the root of the package
                    var cmdScriptPath = Path.Combine(etcPath, "nuget-overlay.cmd");

                    var scriptText = File.ReadAllText(cmdScriptPath).Replace("$$VERSION$$", (string)_nuSpec.metadata.version);

                    var scriptPath = Path.Combine(Directory, @"NuGet-Overlay.cmd");
                    scriptPath.TryHardToDelete();
                    File.WriteAllText(scriptPath, scriptText);
                    temporaryFiles.Add(scriptPath);
                    AddFileToNuSpec(scriptPath, @"\NuGet-Overlay.cmd");

                    var pivotListPath = Path.Combine(Directory, @"pivot-list.txt");
                    pivotListPath.TryHardToDelete();
                    File.WriteAllLines(pivotListPath, overlays.ToArray());
                    temporaryFiles.Add(pivotListPath);
                    AddFileToNuSpec(pivotListPath, @"\build\native\pivot-list.txt");
                }
            }
            else
            {
                // single package
                foreach (var set in _fileSets.Keys)
                {
                    foreach (var src in _fileSets[set].Keys)
                    {
                        AddFileToNuSpec(_fileSets[set][src], src);
                    }
                }
            }

            if (Props.IsValueCreated && Props.Value.Xml.Children.Count > 0)
            {
                Props.Value.FullPath.TryHardToDelete();
                if (Props.Value.Save())
                {
                    temporaryFiles.Add(Props.Value.FullPath);
                    AddFileToNuSpec(Props.Value.FullPath, @"\build\native\{0}".format(Props.Value.Filename));
                }
            }

            if (Targets.IsValueCreated && Targets.Value.Xml.Children.Count > 0)
            {
                Targets.Value.FullPath.TryHardToDelete();
                if (Targets.Value.Save())
                {
                    temporaryFiles.Add(Targets.Value.FullPath);
                    AddFileToNuSpec(Targets.Value.FullPath, @"\build\native\{0}".format(Targets.Value.Filename));
                }
            }

            _nuSpec.Save(FullPath);
            temporaryFiles.Add(FullPath);

            if (PkgRole == PackageRole.@default || !_fileSets.Values.IsNullOrEmpty())
            {
                // don't save the package if it has no files in it.
                if (!generateOnly)
                {
                    packageFileName = NuPack(FullPath);
                    Event <OutputObject> .Raise(new FileInfo(packageFileName.GetFullPath()));
                }
            }

            if (generateOnly)
            {
                foreach (var t in temporaryFiles)
                {
                    Event <OutputObject> .Raise(new FileInfo(t.GetFullPath()));
                }
            }

            if (cleanIntermediateFiles)
            {
                temporaryFiles.ForEach(FilesystemExtensions.TryHardToDelete);
            }
            overlayPackages = overlays ?? Enumerable.Empty <string>();

            return(packageFileName);
        }