public DiffResult BuildDiffResult(IActivityMonitor m, List <Commit> commits) { var commitsAndParents = commits.Select(s => (s, s.Parents.FirstOrDefault())); var commitWithDiff = commitsAndParents.Select(c => (c.s, _git.Diff.Compare <TreeChanges>(c.s.Tree, c.Item2.Tree))).ToList(); Commit firstCommit = commits.First(); Commit lastCommit = commits.Last(); if (firstCommit.Committer.When < lastCommit.Committer.When) { throw new ArgumentException("Unchronological commits order."); } m.Debug($"Diffing between {firstCommit.Sha} and {lastCommit.Sha}"); var fullDiff = _git.Diff.Compare <TreeChanges>(lastCommit.Tree, firstCommit.Tree); using (m.OpenDebug("Finding commits that impacted changes.")) { using (m.OpenDebug("Caching changes")) { foreach (TreeEntryChanges change in fullDiff) { switch (change.Status) { case ChangeKind.Unmodified: m.Debug($"Skipping {change.Path} because: {change.Status}."); continue; case ChangeKind.Added: RunOnBuilders(m, new AddedDiff(change.Path)); break; case ChangeKind.Deleted: RunOnBuilders(m, new DeletedDiff(change.Path)); break; case ChangeKind.Renamed: case ChangeKind.Modified: RunOnBuilders(m, new ModifiedDiff(change.OldPath, change.Path)); break; default: throw new NotImplementedException(); //So it's actually used... i tought it would not. } } } } //all the commits are now cached. return(new DiffResult(true, _diffRootResultBuilders.Select(p => p.Result).ToList(), _others.Result)); }
public XTypedObject CreateInstance(IActivityMonitor monitor, XElement e, IServiceProvider baseProvider = null, Type type = null) { using (monitor.OpenDebug($"Creating XTypedObject from root {e.ToStringPath()}.")) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (monitor == null) { throw new ArgumentNullException(nameof(monitor)); } if (_typeRegister.Count == 0) { AutoRegisterFromLoadedAssemblies(monitor); } e.Changing += PreventAnyChangesToXElement; var eReader = new XElementReader(monitor, e, new HashSet <XObject>()); if (type == null) { type = GetMappping(eReader); } var rootConfig = new XTypedObject.Initializer(this, eReader, baseProvider); var root = (XTypedObject)baseProvider.SimpleObjectCreate(monitor, type, rootConfig); var result = root != null && CreateChildren(root, rootConfig) ? root : null; if (result != null) { eReader.WarnUnhandledAttributes(); } return(result); } }
/// <summary> /// Updates the "Stacks.xml" file. /// </summary> /// <param name="m">The monitor to use.</param> /// <returns>True on success, false on error.</returns> bool WriteStacksToLocalStacksFilePath(IActivityMonitor m) { using (m.OpenDebug($"Saving {StacksFilePath}.")) { try { new XDocument(new XElement("Stacks", _stackRepos.Select(r => r.ToXml()))).Save(StacksFilePath); return(true); } catch (Exception ex) { m.Error(ex); return(false); } } }
internal IEnumerable <XNode> Apply(XElement e) { using (Monitor.OpenDebug($"Applying reusables to {e.ToStringPath()}.")) { if (e.Name == "Reuse") { if (e.Elements().Any(c => c.Name != "Remove")) { Monitor.Error($"Reuse element {e.ToStringPath()} can not have children other than Remove."); return(Array.Empty <XElement>()); } string reusableName = (string)e.AttributeRequired("Name"); IEnumerable <XNode> reusable = Find(reusableName, clone: true); if (reusable == null) { Monitor.Error($"Unable to find reusable named '{reusableName}' from {e.ToStringPath()}."); return(Array.Empty <XElement>()); } Debug.Assert(reusable.OfType <XElement>().DescendantsAndSelf().Any(c => c.Name == "Reuse") == false); Monitor.Debug($"Expanded reusable named '{reusableName}'."); var reusedRoot = new XElement(e.Name, reusable); var removeExpr = e.Elements().Select(r => (string)r.AttributeRequired("Target")).ToList(); foreach (var toRemove in removeExpr) { var removes = reusedRoot.XPathSelectElements(toRemove).ToList(); if (removes.Count == 0) { Monitor.Error($"No match found for Remove Target {toRemove} in Reuse {e.ToStringPath()}."); return(Array.Empty <XElement>()); } foreach (var r in removes) { r.Remove(); } } return(reusedRoot.Nodes()); } var children = e.Nodes().SelectMany(n => n is XElement c ? Apply(c) : new[] { n.Clone() }); return(e.Name == "Reusable" ? children : new[] { new XElement( e.Name, e.Attributes().Select(a => a.Clone()), children).SetLineColumnInfo(e) }); } }
/// <summary> /// Creates an instance of the specified type, using any available services. /// The strategy is to use the longest public constructor. /// </summary> /// <param name="monitor">Monitor to use.</param> /// <param name="t">Type of the object to create.</param> /// <param name="services">Available services to inject.</param> /// <param name="requiredParameters">Optional required parameters.</param> /// <returns>The object instance or null on error.</returns> public static object?Create(IActivityMonitor monitor, Type t, IServiceProvider services, IEnumerable <object>?requiredParameters = null) { Throw.CheckNotNullArgument(monitor); Throw.CheckNotNullArgument(t); using (monitor.OpenDebug($"Creating instance of type: {t.AssemblyQualifiedName}.")) try { Required required = requiredParameters == null ? Array.Empty <KeyValuePair <object?, Type> >() : (Required)requiredParameters.Select(r => new KeyValuePair <object?, Type>(r, r.GetType())).ToList(); var longestCtor = t.GetConstructors() .Select(x => ValueTuple.Create(x, x.GetParameters())) .Where(x => x.Item2.Length >= required.Count) .OrderByDescending(x => x.Item2.Length) .Select(x => new { Ctor = x.Item1, Parameters = x.Item2, Mapped = x.Item2 .Select(p => required.FirstOrDefault(r => p.ParameterType.IsAssignableFrom(r.Value)).Key) .ToArray() }) .Where(x => x.Mapped.Count(m => m != null) == required.Count) .FirstOrDefault(); if (longestCtor == null) { var msg = $"Unable to find a public constructor for '{t.FullName}'."; if (required.Count > 0) { msg += " With required parameters compatible with type: " + required.Select(r => r.Value.Name).Concatenate(); } monitor.Error(msg); return(null); } int failCount = 0; for (int i = 0; i < longestCtor.Mapped.Length; ++i) { if (longestCtor.Mapped[i] == null) { var p = longestCtor.Parameters[i]; var resolved = services.GetService(p.ParameterType); if (resolved == null && !p.HasDefaultValue) { monitor.Error($"Resolution failed for parameter '{p.Name}', type: '{p.ParameterType}'."); ++failCount; } longestCtor.Mapped[i] = resolved; } } if (failCount > 0) { monitor.Error($"Unable to resolve parameters for '{t.FullName}'. Considered longest constructor: {longestCtor.Ctor}."); return(null); } return(longestCtor.Ctor.Invoke(longestCtor.Mapped)); } catch (Exception ex) { monitor.Error($"While instantiating {t.FullName}.", ex); return(null); } }
/// <summary> /// /// </summary> /// <param name="m"></param> /// <param name="solutions"></param> /// <param name="traceGraphDetails"></param> /// <param name="solutionCtx">May be null, used to construct the <see cref="DependencyAnalyzer"/></param> /// <returns></returns> internal static DependencyAnalyzer Create(IActivityMonitor m, IReadOnlyCollection <ISolution> solutions, bool traceGraphDetails, ISolutionContext solutionCtx) { var packages = new Dictionary <Artifact, LocalPackageItem>(); var projectItems = new ProjectItem.Cache(); var externalRefs = new List <PackageReference>(); // Note: Project to project references are translated into Requirements directly // in the ProjectItem constructor. // After having built the ProjectItem, we handle here the Packages (and PackageReferences between // projects). using (m.OpenDebug("Creating all the ProjectItem for all projects in all solutions.")) { foreach (var s in solutions) { using (m.OpenDebug($"Solution {s.Name}.")) { foreach (var project in s.Projects) { projectItems.Create(project); } } } } using (m.OpenDebug("Creating Package for all installable Artifacts in all solutions.")) { foreach (var s in solutions) { using (m.OpenDebug($"Solution {s.Name}.")) { foreach (var project in s.Projects) { foreach (var package in project.GeneratedArtifacts.Where(a => a.Artifact.Type.IsInstallable)) { if (packages.TryGetValue(package.Artifact, out var alreadyPublished)) { m.Error($"'{package.Project.Solution+"->"+package}' is already published by {alreadyPublished.Project.Solution+"->"+alreadyPublished.Project}."); return(null); } packages.Add(package.Artifact, new LocalPackageItem(package.Artifact, project)); m.Debug($"Package '{package}' created."); } } } } } // 3 - Create the requirements between each project and Packages that are bound to a // Published project (the LocalPackageItem previuosly created). // When PackageReferences references external Packages, we add it to the ExternalRefs. foreach (var project in projectItems.AllProjectItems) { // Consider package references (Project to Project references are handled by ProjectItem constructors). foreach (var dep in project.Project.PackageReferences) { if (packages.TryGetValue(dep.Target.Artifact, out LocalPackageItem target)) { if (target.Project.Solution != project.Project.Solution) { project.AddRequires(target); } else { // A project is referencing a Package that is generated by // its own Solution. This can happen (even if it is strange): for instance to test packages // from the solution itself (the more correct way to do this is to use another // Repository/Solution to test the packages since here you always test the "previous" // package version). // // We transform the package reference into a project reference so that this edge // case does not create cycles. project.AddRequires(projectItems[target.Project]); } } else { // Dependency to an external Package. externalRefs.Add(dep); } } } return(new DependencyAnalyzer( m, solutions, solutionCtx, projectItems, externalRefs, traceGraphDetails)); }