private static YumlClassWithDetails MakeClass(DllReference dllReference)
        {
            var detailModel = new YumlClassWithDetails(dllReference.AssemblyName);

            detailModel.Notes.Add(
                string.Format("External Reference{0}",
                              string.IsNullOrWhiteSpace(dllReference.Version) ? "" : string.Format(" ({0})", dllReference.Version)
                              )
                );

            return(detailModel);
        }
Пример #2
0
        public void Save(SemanticVersion version, string name, DllReference parentAssembly)
        {
            var parser           = new FileIniDataParser();
            var versionsFileData = new IniData();

            versionsFileData.Sections.AddSection("Dependency");
            versionsFileData.Sections["Dependency"].AddKey("version", version.ToString());
            versionsFileData.Sections["Dependency"].AddKey("name", name);

            if (!Directory.Exists("cache"))
            {
                Directory.CreateDirectory("cache");
            }

            parser.WriteFile(@"cache\" + parentAssembly.Id.Item1 + _sectionSeparator + parentAssembly.Id.Item2 + _sectionSeparator + name + ".ini", versionsFileData);
        }
Пример #3
0
        public Tuple <SemanticVersion, string> Load(DllReference parentAssembly, string Dependency)
        {
            var path = parentAssembly.Id.Item1 + _sectionSeparator + parentAssembly.Id.Item2 + _sectionSeparator + Dependency + ".ini";

            if (!File.Exists(@"cache\" + path))
            {
                return(null);
            }

            var parser  = new FileIniDataParser();
            var iniData = parser.ReadFile(@"cache\" + path);

            var section = iniData.Sections["Dependency"];
            var version = SemanticVersion.ParseOptionalVersion(section["version"]);
            var name    = section["name"];

            return(new Tuple <SemanticVersion, string>(version, name));
        }
Пример #4
0
        public Tuple <SemanticVersion, string> GetDependencyFromCacheOrResolve(DllReference parentAssembly, AssemblyReference assemblyDependency)
        {
            //RULE 0. it's already in cache
            Tuple <SemanticVersion, string> cachedDependancy = null;

            if (_useCache)
            {
                cachedDependancy = _dependencies.Load(parentAssembly, assemblyDependency.Item2);
            }
            if (cachedDependancy != null)
            {
                return(cachedDependancy);
            }

            var assembly = ResolveAssembly(parentAssembly, assemblyDependency);

            if (assembly != null && _useCache)
            {
                _dependencies.Save(assembly.Item1, assembly.Item2, parentAssembly);
            }

            return(assembly);
        }
Пример #5
0
        private Tuple <SemanticVersion, string> ResolveAssembly(DllReference parentAssembly, AssemblyReference assemblyDependency)
        {
            var assemblies            = _assemblyCacheService.Assemblies;
            var conflictingAssemblies = _assemblyCacheService.ConflictingAssemblies;

            //RULE 1. It's an assembly that is known on nuget.org or other. Official or Snapshot doesn't matter
            if (_resolutionLevel != ResolutionLevelEnum.DontResolveDependancyUsingOfficialRepository)
            {
                var nugetPackage = _mappingService.GetNuGetPackage(_assemblyCacheService, assemblyDependency);
                if (nugetPackage != null)
                {
                    Trace.TraceInformation($"{assemblyDependency.Item2}-{assemblyDependency.Item1} found in official repository as {nugetPackage.Item2}-{nugetPackage.Item1}");
                    return(nugetPackage);
                }
            }

            //RULE 2. The reference is not known but it match with at least one dll present on local folder
            var resolvedAssembly = new Tuple <SemanticVersion, string>(new SemanticVersion(assemblyDependency.Item1), assemblyDependency.Item2);

            if (_assemblyCacheService.Assemblies.ContainsKey(resolvedAssembly) &&
                conflictingAssemblies[assemblyDependency].Count(_ => string.IsNullOrEmpty(_.SpecialVersion)) == 1)
            {
                Trace.TraceInformation($"{assemblyDependency.Item2}-{assemblyDependency.Item1} found at {assemblies[resolvedAssembly].Path}");
                return(assemblies[resolvedAssembly].Id);
            }

            if (conflictingAssemblies.ContainsKey(assemblyDependency) &&
                conflictingAssemblies[assemblyDependency].Count(_ => string.IsNullOrEmpty(_.SpecialVersion)) > 1 &&
                _resolutionLevel != ResolutionLevelEnum.DontResolveDependancyIgnoringMultipleAssembliesWithSameVersion)
            {
                // there might be more than one dll with the expected version...Try to find the best one...
                resolvedAssembly = RetrieveConflictingDependancyFromCacheOrResolve(assemblies, parentAssembly, conflictingAssemblies[assemblyDependency], assemblyDependency);
            }


            // RULE 3. Let's try to find if there is a snapshot or a equivalent Version (build number mistmatch only)
            if (_resolutionLevel != ResolutionLevelEnum.DontResolveDependancyIgnoringBuildNumber)
            {
                var resolvedpackage = CompatibleBuild(assemblyDependency, assemblies, resolvedAssembly);
                if (resolvedpackage != null)
                {
                    return(resolvedpackage);
                }
            }


            // RULE 4. Let's try to find if there is Higher Version (Patch & Build only) and take it only if there is only one possibility
            if (_resolutionLevel != ResolutionLevelEnum.DontResolveDependancyIgnoringPatchAndBuildNumber)
            {
                var resolvedpackage = ComptiblePathAndBuild(assemblyDependency, assemblies, resolvedAssembly);
                if (resolvedpackage != null)
                {
                    return(resolvedpackage);
                }
            }

            Trace.TraceError($"Unable to find dependency {assemblyDependency.Item2}, {assemblyDependency.Item1}");
            if (_useCache)
            {
                _dependencies.AddUnresolvedDependencies(assemblyDependency);
            }

            return(null);
        }
Пример #6
0
        /// <summary>
        /// Marked as internal for unit test purpose. In charge of fetching all the version of an assembly and analyze the public
        /// API to know if there were breaking change or not
        /// </summary>
        internal Tuple <SemanticVersion, string> ResolveConflictingDependancy(IEnumerable <DllReference> conflictingAssembliesVersions, DllReference parentAssembly)
        {
            var         diffs       = new List <AssemblyDiffCollection>();
            DiffPrinter diffPrinter = new DiffPrinter();

            //Skip SemanticVersion until we reach the official SemanticVersion supported
            var asms = conflictingAssembliesVersions.Reverse();

            asms = asms.Reverse();

            //We start to next one as we already set PreviousAPI...
            var previousAPIAssembly = asms.FirstOrDefault();

            asms = asms.Skip(1);
            DllReference selectedVersion = previousAPIAssembly;

            foreach (var apiAssembly in asms)
            {
                diffs = new List <AssemblyDiffCollection>();
                AssemblyDiffCollection diff = null;
                try
                {
                    if (previousAPIAssembly.Path != null && apiAssembly.Path != null)
                    {
                        diff =
                            new AssemblyDiffer(previousAPIAssembly.Path, apiAssembly.Path).GenerateTypeDiff(
                                QueryAggregator.AllExternallyVisibleApis);
                    }
                    //The previous assembly doesn't have any path we can compare with let's forget it
                    else if (previousAPIAssembly.Path == null && apiAssembly.Path != null)
                    {
                        previousAPIAssembly = apiAssembly;
                        continue;
                    }
                    //Current assembly doesn't have any path we can use to compare, ignore it
                    else
                    {
                        continue;
                    }

                    //Nothing Was added between those 2 versions...Strange but let's go ahead
                    if (diff.AddedRemovedTypes.Count <= 0 && diff.ChangedTypes.Count <= 0)
                    {
                        previousAPIAssembly = apiAssembly;
                        continue;
                    }


                    diffs.Add(diff);

                    var aggregator = new UsageQueryAggregator();

                    var breakingChangeSearcher =
                        AppDomain.CurrentDomain.CreateInstanceAndUnwrap(
                            "ApiChange.Api, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
                            "ApiChange.Api.Introspection.Diff.BreakingChangeSearcher", true,
                            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null,
                            new object[] { diffs, aggregator }, null, null);
                    AssemblyDefinition assembly =
                        AssemblyLoader.LoadCecilAssembly(parentAssembly.Path, false);

                    if (assembly != null)
                    {
                        aggregator.Analyze(assembly);
                    }

                    //None of New Types, methods, fields etc. are used in assembly
                    //So we stop here and return the previous one
                    if (aggregator.AssemblyMatches.Count != 0 ||
                        aggregator.TypeMatches.Count != 0 ||
                        aggregator.MethodMatches.Count != 0 ||
                        aggregator.FieldMatches.Count != 0)
                    {
                        selectedVersion = apiAssembly;
                    }
                }
                catch (Exception exc)
                {
                    Trace.TraceError(exc.Message);
                    Trace.TraceError(exc.StackTrace);
                    Trace.TraceError(String.Format("Unable to diff assembly from {0} to {1}", previousAPIAssembly, apiAssembly));
                    //We don't set the prevous assembly because the current raised an exception, let's ignore it totally
                    continue;
                }
                previousAPIAssembly = apiAssembly;
            }
            return(new Tuple <SemanticVersion, string>(selectedVersion.Id.Item1, selectedVersion.Id.Item2));
        }
Пример #7
0
        /// <summary>
        /// Try to retrieve dependancies from cache if it was already compute, if not try to resolve it
        /// </summary>
        internal Tuple <SemanticVersion, string> RetrieveConflictingDependancyFromCacheOrResolve(SortedDictionary <Tuple <SemanticVersion, string>, DllReference> assemblies,
                                                                                                 DllReference parentAssembly, SortedSet <SemanticVersion> assembliesSemanticVersions,
                                                                                                 AssemblyReference assemblyDependency)
        {
            var asmss = assembliesSemanticVersions
                        .Select(_ =>
            {
                try
                {
                    return(assemblies[new Tuple <SemanticVersion, string>(_, assemblyDependency.Item2)]);
                }
                catch (KeyNotFoundException exc)
                {
                    var excption = new VersionNotFoundException(String.Format("versions.ini is not consistent with assemblies.ini. versions.ini is referencing {1}-{0} while it doesn't exist in Assemblies.ini", _, assemblyDependency.Item2), exc);
                    throw excption;
                }
            })
                        //If Parent assembly is a snapshot we include snapshot in dependency otherwise no because nuget doesn't support
                        // official package with snapshot dependency
                        .Where(_ =>
                               (string.IsNullOrEmpty(parentAssembly.Id.Item1.SpecialVersion) &&
                                !string.IsNullOrEmpty(_.Id.Item1.SpecialVersion))
                        ? false
                        : true
                               );

            var result = ResolveConflictingDependancy(asmss, parentAssembly);

            return(result);
        }
Пример #8
0
        private DllReference GetDllReference(XmlNode parent)
        {
            var itemArray = parent.Attributes["Include"].Value.Split(',');

            var includeAttributes = itemArray.Skip(1).Select(item => item.Split('=')).ToDictionary(item => item[0].Trim(' '), item => item[1].Trim(' '));

            var reference = new DllReference { Name = itemArray[0].Trim(' '), CopyLocal = false };

            reference.Version = GetValue(includeAttributes, "Version", null);
            reference.Culture = GetValue(includeAttributes, "Culture", null);
            reference.PublicKey = GetValue(includeAttributes, "PublicKeyToken", null);
            reference.ProcessorArchitecture = GetValue(includeAttributes, "processorArchitecture", null);

            reference.CopyLocal = bool.Parse(GetChildElementValueSafely(parent, "Private", "False"));
            reference.SpecificVersion = bool.Parse(GetChildElementValueSafely(parent, "SpecificVersion", "False"));
            reference.Path = GetChildElementValueSafely(parent, "HintPath", null);

            return reference;
        }
Пример #9
0
 public static bool IsNuGetDllReference(this DllReference dllReference)
 {
     return(false);
 }