Example #1
0
        private static JToken NugetInfoJson(NugetInformationModel nugetInformationModel)
        {
            var writer = new JTokenWriter();

            writer.WriteStartObject();

            writer.WritePropertyName("name");
            writer.WriteValue(nugetInformationModel.Project.Name);

            writer.WritePropertyName("id");
            writer.WriteValue(nugetInformationModel.Project.Id);

            writer.WritePropertyName("ignored");
            writer.WriteValue(nugetInformationModel.Project.Ignored);

            writer.WritePropertyName("projects");
            writer.WriteStartArray();

            foreach (var project in nugetInformationModel.ProjectModels)
            {
                writer.WriteStartObject();

                writer.WritePropertyName("assemblyName");
                writer.WriteValue(project.AssemblyName);

                writer.WritePropertyName("csprojFilePath");
                writer.WriteValue(project.CsprojFilePath);

                writer.WritePropertyName("nuspecPath");
                writer.WriteValue(project.NuspecPath);

                writer.WritePropertyName("nugetSpecification");
                if (project.Self == null)
                {
                    writer.WriteValue((object)null);
                }
                else
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("id");
                    writer.WriteValue(project.Self.Id);

                    writer.WritePropertyName("version");
                    writer.WriteValue(project.Self.Version);

                    writer.WriteEndObject();
                }

                writer.WritePropertyName("dependencies");
                writer.WriteStartArray();

                foreach (var dependency in project.Dependencies)
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("id");
                    writer.WriteValue(dependency.Id);

                    writer.WritePropertyName("version");
                    writer.WriteValue(dependency.Version);

                    writer.WriteEndObject();
                }

                writer.WriteEndArray();

                writer.WriteEndObject();
            }

            writer.WriteEndArray();
            writer.WriteEndObject();

            return(writer.Token);
        }
Example #2
0
        private static NugetInformationModel GetNugetInformation(GitProjectModel project, StringComparison oic)
        {
            void IterateTree(Tree[] trees, List <NugetMetaObject> nugetMetaObjects)
            {
                foreach (var tree in trees)
                {
                    if (tree.Type == Tree.TreeType.File)
                    {
                        var culture = StringComparison.OrdinalIgnoreCase;
                        if (tree.Name.Equals("packages.config", culture))
                        {
                            nugetMetaObjects.Add(new NugetMetaObject(tree.Path, NugetMetaObject.NugetMetaObjectType.PackagesConfig));
                            continue;
                        }

                        if (tree.Name.EndsWith(".csproj", culture))
                        {
                            nugetMetaObjects.Add(new NugetMetaObject(tree.Path, NugetMetaObject.NugetMetaObjectType.Csproj));
                            continue;
                        }

                        if (tree.Name.EndsWith(".nuspec", culture))
                        {
                            nugetMetaObjects.Add(new NugetMetaObject(tree.Path, NugetMetaObject.NugetMetaObjectType.Nuspec));
                            continue;
                        }
                    }
                    else if (tree.Type == Tree.TreeType.Folder)
                    {
                        IterateTree(tree.Children, nugetMetaObjects);
                    }
                }
            }

            {
                var projectIdentifierMsg = project.Name + " (id:" + project.Id + ")";

                var information = project.GetInformation();
                var nugetMeta   = new List <NugetMetaObject>();
                var folderTree  = information.Tree;
                IterateTree(folderTree, nugetMeta);

                var nugetInfo = new NugetInformationModel();
                nugetInfo.Project = project;
                // search for definitions
                var nuspecs = nugetMeta.Where(m => m.Type == NugetMetaObject.NugetMetaObjectType.Nuspec).ToArray();
                //if (nuspecs.Length > 1)
                //    throw new Exception($"{projectIdentifierMsg} has {nuspecs.Length} nuspec files");

                #region Nuspec fetch

                JObject specialConfigJson = null;
                var     specialConfiguredNugetProjects = new Dictionary <string, string>();


                var specialConfig = folderTree.SingleOrDefault(f => f.Type == Tree.TreeType.File && f.Name == "config.aprmst");
                if (specialConfig != null)
                {
                    var specialConfigBlob = (Blob)information.Commit[specialConfig.Path].Target;
                    specialConfigJson = JsonConvert.DeserializeObject <JObject>(specialConfigBlob.GetContentText());

                    var nugetProjects = (specialConfigJson["nuget-projects"] as JArray);
                    if (nugetProjects != null)
                    {
                        foreach (var nugetProject in nugetProjects.Values <string>())
                        {
                            var treeEntry     = information.Commit.Tree[nugetProject];
                            var csprojBlob    = (Blob)treeEntry.Target;
                            var csprojContent = csprojBlob.GetContentText();

                            XmlDocument csprojDoc = new XmlDocument();
                            csprojDoc.LoadXml(csprojContent);

                            string csprojJson  = JsonConvert.SerializeXmlNode(csprojDoc);
                            var    csprojToken = JsonConvert.DeserializeObject <JToken>(csprojJson);

                            var assemblyName = csprojToken["Project"]["PropertyGroup"].Values <string>("AssemblyName").Single();

                            specialConfiguredNugetProjects.Add(treeEntry.Path, assemblyName);
                        }
                    }
                }

                foreach (var nugetMetaObject in nuspecs)
                {
                    var nugetProjectModel = new NugetProjectModel();

                    var blob    = (Blob)information.Commit.Tree[nugetMetaObject.Path].Target;
                    var content = blob.GetContentText();

                    var doc = new XmlDocument();
                    doc.LoadXml(content);

                    string json  = JsonConvert.SerializeXmlNode(doc);
                    var    token = JsonConvert.DeserializeObject <JToken>(json);

                    var nuspecTokens = new Dictionary <string, string>();
                    var rawPackageId = token["package"]["metadata"].Value <string>("id");

                    if (string.IsNullOrWhiteSpace(rawPackageId))
                    {
                        throw new Exception($"{projectIdentifierMsg} is missing id in nuspec: {nugetMetaObject.Path}");
                    }

                    var packageId = new NuspecString(rawPackageId, nuspecTokens);

                    string relatedCsprojFile = null;

                    var nuspecNamespace = new XmlNamespaceManager(doc.NameTable);
                    nuspecNamespace.AddNamespace("ns", doc.DocumentElement.GetAttribute("xmlns"));

                    var metaData = doc.SelectNodes("/ns:package/ns:metadata/comment()", nuspecNamespace);

                    const string forcedRelatedCsprojName = "and3k5:relatedCsproj";

                    foreach (XmlComment comment in metaData)
                    {
                        if (comment.Value == null)
                        {
                            continue;
                        }
                        var matches = Regex.Matches(comment.Value, @"and3k5:relatedCsproj\s*=\s*""(?<csprojPath>[^""]+)""", RegexOptions.Multiline);

                        var path = matches.IterateThrough <Match>().SingleOrDefault()?.Groups["csprojPath"];

                        if (path != null)
                        {
                            relatedCsprojFile = path.Value.Replace("\\", "/");
                        }
                    }

                    if (relatedCsprojFile == null)
                    {
                        var filesToken = token["package"]["files"]?["file"];

                        if (filesToken == null)
                        {
                            throw new Exception($"{projectIdentifierMsg} has no files in nuspec: {nugetMetaObject.Path}");
                        }

                        var files = new List <string>();

                        switch (filesToken)
                        {
                        case JObject _:
                            files.Add(new NuspecString(filesToken.Value <string>("@src"), nuspecTokens).ToString());
                            break;

                        case JArray _:
                            foreach (var fileItem in (JArray)filesToken)
                            {
                                files.Add(new NuspecString(fileItem.Value <string>("@src"), nuspecTokens).ToString());
                            }

                            break;

                        default:
                            throw new Exception($"{projectIdentifierMsg} has unknown filesToken type: {filesToken.GetType().Name} nuspec: {nugetMetaObject.Path}");
                        }

                        var folderPaths = files.Select(f => f.Split(new char[] { '\\', '/' }, StringSplitOptions.None)).Select(x => x.Take(x.Length - 1).ToArray()).GroupBy(x => string.Join("/", x)).Select(x => x.First());

                        var relatedCsprojFiles = new List <string>();
                        foreach (var folderPath in folderPaths)
                        {
                            for (var i = folderPath.Length - 1; i >= 0; i--)
                            {
                                var path  = string.Join("/", folderPath.Take(i + 1).ToArray());
                                var entry = information.Commit[path];
                                if (entry == null)
                                {
                                    continue;
                                }
                                var tree = (LibGit2Sharp.Tree)entry.Target;
                                foreach (var treeEntry in tree)
                                {
                                    if (treeEntry.TargetType != TreeEntryTargetType.Blob)
                                    {
                                        continue;
                                    }
                                    if (treeEntry.Name.EndsWith(".csproj", oic))
                                    {
                                        relatedCsprojFiles.Add(treeEntry.Path);
                                    }
                                }
                            }
                        }

                        relatedCsprojFiles = relatedCsprojFiles.Distinct().ToList();
                        //if (relatedCsprojFiles.Count == 0)
                        //    throw new Exception($"{projectIdentifierMsg} has no related csproj files for nuspec: {nuspecs[0].Path}");
                        if (relatedCsprojFiles.Count > 1)
                        {
                            throw new Exception($"{projectIdentifierMsg} has multiple related csproj files for nuspec: {nugetMetaObject.Path} {Environment.NewLine}Files: " + string.Join(Environment.NewLine, relatedCsprojFiles.OrderByDescending(x => x.Split(new char[] { '\\', '/' }, StringSplitOptions.None).Length)));
                        }

                        relatedCsprojFile = relatedCsprojFiles.ElementAtOrDefault(0);
                    }

                    nugetProjectModel.Self = new NugetPackageModel()
                    {
                        Id = packageId.ToString(),
                    };

                    nugetProjectModel.CsprojFilePath = relatedCsprojFile;
                    nugetProjectModel.NuspecPath     = nugetMetaObject.Path;
                    if (relatedCsprojFile != null)
                    {
                        var csprojBlob    = (Blob)information.Commit.Tree[relatedCsprojFile].Target;
                        var csprojContent = csprojBlob.GetContentText();

                        XmlDocument csprojDoc = new XmlDocument();
                        csprojDoc.LoadXml(csprojContent);

                        string csprojJson  = JsonConvert.SerializeXmlNode(csprojDoc);
                        var    csprojToken = JsonConvert.DeserializeObject <JToken>(csprojJson);

                        nugetProjectModel.AssemblyName = csprojToken["Project"]["PropertyGroup"].Values <string>("AssemblyName").Single();

                        nugetInfo.ProjectModels.Add(nugetProjectModel);
                    }
                }

                #endregion

                var csprojs = nugetMeta.Where(m => m.Type == NugetMetaObject.NugetMetaObjectType.Csproj).ToArray();
                foreach (var csproj in csprojs)
                {
                    NugetProjectModel nugetProject = nugetInfo.ProjectModels.SingleOrDefault(p => p.CsprojFilePath.Equals(csproj.Path));

                    var csprojBlob    = (Blob)information.Commit.Tree[csproj.Path].Target;
                    var csprojContent = csprojBlob.GetContentText();

                    XmlDocument csprojDoc = new XmlDocument();
                    csprojDoc.LoadXml(csprojContent);

                    string csprojJson  = JsonConvert.SerializeXmlNode(csprojDoc);
                    var    csprojToken = JsonConvert.DeserializeObject <JToken>(csprojJson);

                    if (nugetProject == null)
                    {
                        if (csprojToken["Project"] == null)
                        {
                            continue;
                        }

                        if (IsCoreOrStandard(csprojToken))
                        {
                            continue;
                        }

                        nugetProject = new NugetProjectModel
                        {
                            AssemblyName   = csprojToken["Project"]["PropertyGroup"].Values <string>("AssemblyName").Single(),
                            CsprojFilePath = csproj.Path,
                        };

                        if (specialConfiguredNugetProjects.ContainsKey(csproj.Path))
                        {
                            nugetProject.Self = new NugetPackageModel()
                            {
                                Id = nugetProject.AssemblyName,
                            };
                        }

                        nugetInfo.ProjectModels.Add(nugetProject);
                    }

                    var csprojSegments     = csproj.Path.Split(new char[] { '\\', '/' }, StringSplitOptions.None);
                    var csprojFolderPath   = csprojSegments.Take(csprojSegments.Length - 1);
                    var packagesConfigFile = nugetMeta.Where(p => p.Type == NugetMetaObject.NugetMetaObjectType.PackagesConfig).Select(m => m.Path.Split(new char[] { '\\', '/' }, StringSplitOptions.None)).SingleOrDefault(p => p.Take(p.Length - 1).SequenceEqual(csprojFolderPath));
                    if (packagesConfigFile != null)
                    {
                        var packagesConfigBlob    = (Blob)information.Commit.Tree[string.Join("/", packagesConfigFile)].Target;
                        var packagesConfigContent = packagesConfigBlob.GetContentText();

                        XmlDocument packagesConfigDoc = new XmlDocument();
                        packagesConfigDoc.LoadXml(packagesConfigContent);

                        string packagesConfigJson  = JsonConvert.SerializeXmlNode(packagesConfigDoc);
                        var    packagesConfigToken = JsonConvert.DeserializeObject <JToken>(packagesConfigJson);


                        foreach (var dependencyToken in packagesConfigToken["packages"]["package"].ForceToArray())
                        {
                            nugetProject.Dependencies.Add(new NugetPackageModel()
                            {
                                Id      = dependencyToken.Value <string>("@id"),
                                Version = dependencyToken.Value <string>("@version"),
                            });
                        }
                    }
                }

                if (csprojs.Length == 0 && nugetInfo.ProjectModels.Count == 0)
                {
                    // this library has no csproj files. maybe its just a dll file

                    foreach (var nugetMetaObject in nuspecs)
                    {
                        var blob    = (Blob)information.Commit.Tree[nugetMetaObject.Path].Target;
                        var content = blob.GetContentText();

                        var doc = new XmlDocument();
                        doc.LoadXml(content);

                        string json  = JsonConvert.SerializeXmlNode(doc);
                        var    token = JsonConvert.DeserializeObject <JToken>(json);

                        var rawPackageId = token["package"]["metadata"].Value <string>("id");

                        if (string.IsNullOrWhiteSpace(rawPackageId))
                        {
                            throw new Exception($"{projectIdentifierMsg} is missing id in nuspec: {nugetMetaObject.Path}");
                        }

                        var packageId = new NuspecString(rawPackageId);

                        var nugetProjectModel = new NugetProjectModel();
                        nugetProjectModel.Self = new NugetPackageModel()
                        {
                            Id = packageId.ToString(),
                        };
                        nugetProjectModel.NuspecPath = nugetMetaObject.Path;
                        nugetInfo.ProjectModels.Add(nugetProjectModel);
                    }
                }

                return(nugetInfo);
            }
        }