Example #1
0
        private void WritePkgDef(VsixProperties props, Logger l)
        {
            var content = string.Format(_pkgDefTemplate, props.Id);
            var path    = Path.Combine(_rootDir, "template.pkgdef");

            File.WriteAllText(path, content);
        }
Example #2
0
        public static VsixProject Create(string rootDir, VsixProperties props, Logger l)
        {
            var vsixProject = _vsixProjectTemplate.Value;
            var doc         = XDocument.Parse(vsixProject);
            var project     = new VsixProject(rootDir, doc);

            project.WriteManifest(props, l);
            project.WritePkgDef(props, l);

            return(project);
        }
Example #3
0
        public static async Task <int> PackVsix(
            string source,
            string vsix,
            bool force,
            string obj,
            string vsixVersion,
            string moreInfo,
            string licenseFile,
            string releaseNotes,
            string packageIcon,
            string previewImg,
            string[] packageTags,
            string gettingStarted,
            string[] templateIcon,
            string[] languageTag,
            string[] platformTags,
            string[] typeTags,
            string[] defaultName)
        {
            var l = new Logger();

            if (source is null)
            {
                l.LogError("No source file given. Pass --help to show help text.");
                return(1);
            }
            if (!File.Exists(source))
            {
                l.LogError($"Source file '{source}' does not exist.");
                return(1);
            }

            l.Log($"Generating VSIX template package for '{source}'.");

            var templateIconMappings = templateIcon?.Select(s => new TemplatePropertyMapping(s));
            var languageTagMappings  = languageTag?.Select(s => new TemplatePropertyMapping(s));
            var platformTagsMappings = platformTags?.Select(s => new TemplatePropertyMapping(s));
            var typeTagsMappings     = typeTags?.Select(s => new TemplatePropertyMapping(s));
            var defaultNameMappings  = defaultName?.Select(s => new TemplatePropertyMapping(s));

            l.Log("Parsing NuGet metadata.");

            var pkg = await NuPackage.Open(source);

            var metadata  = pkg.Metadata;
            var vsixProps = VsixProperties.FromNuspec(metadata);

            var sourceFolder = Path.GetDirectoryName(source);

            vsix = vsix ?? Path.Combine(sourceFolder, vsixProps.Id + ".vsix");

            if (File.Exists(vsix) && !force)
            {
                l.LogError($"File exists at output path '{vsix}'. Set the --force flag to overwrite it.");
                return(1);
            }

            if (vsixVersion != null)
            {
                vsixProps.Version = vsixVersion;
            }
            if (moreInfo != null)
            {
                vsixProps.MoreInfo = moreInfo;
            }
            if (licenseFile != null)
            {
                vsixProps.License = licenseFile;
            }
            if (releaseNotes != null)
            {
                vsixProps.ReleaseNotes = releaseNotes;
            }
            if (packageIcon != null)
            {
                vsixProps.Icon = packageIcon;
            }
            if (previewImg != null)
            {
                vsixProps.PreviewImage = previewImg;
            }
            if (packageTags != null)
            {
                var splitPackageTags = packageTags.SelectMany(ts => ts.Split(new char[0], StringSplitOptions.RemoveEmptyEntries));
                vsixProps.Tags = string.Join(';', splitPackageTags);
            }
            if (gettingStarted != null)
            {
                vsixProps.GettingStartedGuide = gettingStarted;
            }

            var archive           = pkg.Archive;
            var templateJsonFiles = archive.Entries.Where(e => e.FullName.EndsWith(".template.config/template.json"));

            l.Log("Generating .vstemplate files.");

            var templateContexts = new List <TemplateContext>();

            foreach (var templateJsonFile in templateJsonFiles)
            {
                var templateJsonContent = new StreamReader(templateJsonFile.Open()).ReadToEnd();

                // TODO apply props overrides
                var props = TemplateProperties.ParseTemplateJson(templateJsonContent);

                props.Icon = MapTemplateProperties(props.Identity, templateIconMappings)?.FirstOrDefault();
                if (languageTagMappings != null && languageTagMappings.Any())
                {
                    props.LanguageTag = MapTemplateProperties(props.Identity, languageTagMappings)?.FirstOrDefault() ?? props.LanguageTag;
                }
                props.PlatformTags    = MapTemplateProperties(props.Identity, platformTagsMappings);
                props.ProjectTypeTags = MapTemplateProperties(props.Identity, typeTagsMappings);

                props.DefaultName = MapTemplateProperties(props.Identity, defaultNameMappings)?.FirstOrDefault() ?? props.DefaultName;

                var vsTemplate = CreateVSTemplate(true, props);

                var context = new TemplateContext(templateJsonContent, props, vsTemplate);
                templateContexts.Add(context);
            }

            var di = Directory.CreateDirectory(obj);

            // clear obj directory
            foreach (var fi in di.GetFiles())
            {
                fi.Delete();
            }
            foreach (var fi in di.GetDirectories())
            {
                fi.Delete(true);
            }

            l.Log("Creating VSIX project.");
            l.Indent();

            var vsixDir = Path.Combine(obj, "Vsix");

            Directory.CreateDirectory(vsixDir);

            var vsixProject = VsixProject.Create(vsixDir, vsixProps, l);

            var vsixProjectPath = Path.Combine(vsixDir, "Vsix.csproj");

            var sourceFileName = Path.GetFileName(source);

            File.Copy(source, Path.Combine(vsixDir, sourceFileName));
            vsixProject.AddNupkg(sourceFileName);

            foreach (var ctx in templateContexts)
            {
                var zipFileName = ctx.TemplateJsonProps.Identity + ".zip";

                var tmpZipFolder = Path.Combine(obj, "zip", ctx.TemplateJsonProps.Identity);
                Directory.CreateDirectory(tmpZipFolder);

                File.WriteAllText(Path.Combine(tmpZipFolder, "template.json"), ctx.TemplateJsonContent);
                ctx.VSTemplate.Write(Path.Combine(tmpZipFolder, "template.vstemplate"));

                if (ctx.TemplateJsonProps.Icon != null)
                {
                    File.Copy(ctx.TemplateJsonProps.Icon, Path.Combine(tmpZipFolder, ctx.TemplateJsonProps.IconZipPath));
                }

                ZipFile.CreateFromDirectory(tmpZipFolder, Path.Combine(vsixDir, zipFileName));
                vsixProject.AddTemplateZip(zipFileName, Path.Combine("Templates", ctx.TemplateJsonProps.Identity));

                l.Log($"Added template '{ctx.TemplateJsonProps.Identity}'.");
            }

            vsixProject.Write(vsixProjectPath);

            l.Dedent();

            if (!BuildVsix(l, obj, vsixProjectPath))
            {
                l.LogError("Failed to build vsix.");
                return(1);
            }

            var builtVsixPath = Path.Combine(vsixDir, "bin", "Vsix.vsix");
            var outputVsixDir = Path.GetDirectoryName(vsix);

            if (!Directory.Exists(outputVsixDir))
            {
                Directory.CreateDirectory(outputVsixDir);
            }

            File.Copy(builtVsixPath, vsix, force);

            l.Log($"VSIX generated at {Path.GetFullPath(vsix)}.");

            return(0);
        }
Example #4
0
        private void WriteManifest(VsixProperties props, Logger l)
        {
            // The elements here need to be in this exact order or schema validation for the manifest fails.

            var doc      = XDocument.Parse(_vsixManifestTemplate.Value);
            var metadata = doc.Descendants(_metadataName).First();

            var identity = new XElement(_identityName);

            identity.SetAttributeValue(_idAttrName, props.Id);
            identity.SetAttributeValue(_versionAttrName, props.Version);
            identity.SetAttributeValue(_publisherAttrName, props.Publisher);
            identity.SetAttributeValue(_languageAttrName, "en-us");
            metadata.Add(identity);

            if (props.DisplayName != null)
            {
                metadata.AddElement(_displayNameName, props.DisplayName);
            }
            if (props.Description != null)
            {
                metadata.AddElement(_descriptionName, props.Description);
            }
            if (props.MoreInfo != null)
            {
                metadata.AddElement(_moreInfoName, props.MoreInfo);
            }

            // License
            if (props.License != null)
            {
                var ext       = Path.GetExtension(props.License);
                var localName = "license" + ext;
                if (AddExternalContent(props.License, localName, l))
                {
                    metadata.AddElement(_licenseName, localName);
                }
            }

            // GettingStartedGuide - http(s) URL or local .html file
            if (props.GettingStartedGuide != null)
            {
                var isWebUrl = Uri.TryCreate(props.GettingStartedGuide, UriKind.RelativeOrAbsolute, out var uri) && uri.Scheme.StartsWith("http");
                if (isWebUrl)
                {
                    metadata.AddElement(_gettingStartedGuideName, props.GettingStartedGuide);
                }
                else
                {
                    var ext       = Path.GetExtension(props.GettingStartedGuide);
                    var localName = "getting-started" + ext;
                    if (AddExternalContent(props.GettingStartedGuide, localName, l))
                    {
                        metadata.AddElement(_gettingStartedGuideName, localName);
                    }
                }
            }

            // ReleaseNotes - http(s) URL or local file
            if (props.ReleaseNotes != null)
            {
                var isWebUrl = Uri.TryCreate(props.ReleaseNotes, UriKind.RelativeOrAbsolute, out var uri) && uri.Scheme.StartsWith("http");
                if (isWebUrl)
                {
                    metadata.AddElement(_releaseNotesName, props.ReleaseNotes);
                }
                else
                {
                    var ext       = Path.GetExtension(props.ReleaseNotes);
                    var localName = "release-notes" + ext;
                    if (AddExternalContent(props.ReleaseNotes, localName, l))
                    {
                        metadata.AddElement(_releaseNotesName, localName);
                    }
                }
            }

            // Icon
            if (props.Icon != null)
            {
                var ext       = Path.GetExtension(props.Icon);
                var localName = "icon" + ext;
                if (AddExternalContent(props.Icon, localName, l))
                {
                    metadata.AddElement(_iconName, localName);
                }
            }

            // PreviewImage
            if (props.PreviewImage != null)
            {
                var ext = Path.GetExtension(props.PreviewImage);
                if (props.PreviewImage == props.Icon)
                {
                    var localName = "icon" + ext;
                    metadata.AddElement(_previewImageName, localName);
                }
                else
                {
                    var localName = "preview" + ext;
                    if (AddExternalContent(props.PreviewImage, localName, l))
                    {
                        metadata.AddElement(_previewImageName, localName);
                    }
                }
            }

            if (props.Tags != null)
            {
                metadata.AddElement(_tagsName, props.Tags);
            }

            var path = Path.Combine(_rootDir, "source.extension.vsixmanifest");

            doc.Save(path);
        }