/// <summary> /// Determines the packages needed for merging, including dependencies if necessary. /// </summary> /// <param name="distarr">packages selected for merging</param> /// <param name="mopts">merge options</param> /// <param name="downloader">the downloader</param> /// <param name="scheduled">output list of packages scheduled for merge</param> private void ScheduleMerges(IDistribution[] distarr, MergeOptions mopts, Downloader downloader, out List<MergeEventArgs> scheduled) { scheduled = new List<MergeEventArgs>(); DependencyGraph dg = DependencyGraph.Compute(distarr); IDistribution[] distdeparr = dg.SortedNodes.ToArray(); DependencyGraph.Conflict[] conflicts = dg.FindSlotConflicts(); if (conflicts.Length > 0) throw new SlotConflictException(conflicts); for (int i = 0; i < distdeparr.Length; i++) { IDistribution dist = distdeparr[i]; Atom current = _pkgmgr .FindPackages(Atom.Parse(dist.Package.FullName, AtomParseOptions.WithoutVersion)) .Where(n => n.Slot == dist.Slot) .SingleOrDefault(); bool realselect = distarr.Contains(dist); if (!realselect && current != null && !mopts.HasFlag(MergeOptions.Deep) && dg.CheckSatisfies(current)) dist = dist.PortsTree.Lookup(current); MergeEventArgs mea = new MergeEventArgs(); mea.Previous = current; mea.Selected = realselect && !mopts.HasFlag(MergeOptions.OneShot); mea.Distribution = dist; mea.FetchOnly = mopts.HasFlag(MergeOptions.FetchOnly); mea.HardMask = dist.PortsTree.IsHardMasked(dist); mea.KeywordMask = dist.PortsTree.IsKeywordMasked(dist); mea.KeywordsNeeded = dist.Keywords .Where(kw => _cfg.AcceptKeywords.Contains(kw) || _cfg.AcceptKeywords.Contains(Distribution.GetKeywordName(kw))) .ToArray(); if (!mopts.HasFlag(MergeOptions.Pretend) && (mea.HardMask || mea.KeywordMask)) throw new MaskedPackageException(dist.Package.FullName); if (current == null) mea.Flags |= MergeFlags.New; if (!mea.Flags.HasFlag(MergeFlags.New) && current.Version == dist.Version) mea.Flags |= MergeFlags.Replacing; if (!mea.Flags.HasFlag(MergeFlags.New) && !mea.Flags.HasFlag(MergeFlags.Replacing)) mea.Flags |= MergeFlags.Updating; if (!mea.Flags.HasFlag(MergeFlags.New) && current.Version > dist.Version) mea.Flags |= MergeFlags.Downgrading; if (dist.Slot > 0) mea.Flags |= MergeFlags.Slot; if (dist.Interactive) mea.Flags |= MergeFlags.Interactive; /* TODO block */ if (mea.Flags.HasFlag(MergeFlags.Updating)) mea.Selected = _pkgmgr.IsSelected(dist.Atom); if (dist.FetchRestriction && Distribution.CheckSourcesExist(dist, _cfg.DistFilesDir)) mea.Flags |= MergeFlags.FetchExists; else if (dist.FetchRestriction) mea.Flags |= MergeFlags.FetchNeeded; if (mea.Flags.HasFlag(MergeFlags.Replacing) && (!realselect || mopts.HasFlag(MergeOptions.NoReplace)) && !mopts.HasFlag(MergeOptions.EmptyTree)) continue; if (mea.Flags.HasFlag(MergeFlags.FetchNeeded) && !mopts.HasFlag(MergeOptions.Pretend)) { throw new InstallException("Fetch restriction is enabled for " + dist.ToString() + "\nCopy the package archive into " + _cfg.DistFilesDir); } if (!(mea.Flags.HasFlag(MergeFlags.FetchExists) || mea.Flags.HasFlag(MergeFlags.FetchNeeded))) mea.FetchHandle = downloader.Enqueue(dist); scheduled.Add(mea); } }