/// <summary> /// Handler for the MergeWorker.OnRealMerge event. /// </summary> /// <param name="sender">the merge worker</param> /// <param name="e">merge event args</param> public void MergeWorker_OnRealMerge(object sender, MergeEventArgs e) { if (e.FetchOnly) Console.Write("\n>>> Fetching ("); else Console.Write("\n>>> Merging ("); Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(e.CurrentIter); Console.ResetColor(); Console.Write(" of "); Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(e.TotalMerges); Console.ResetColor(); Console.Write(") "); Console.ForegroundColor = ConsoleColor.Green; Console.Write(e.Distribution.ToString()); Console.ResetColor(); Console.Write("\n"); }
/// <summary> /// Handler for the MergeWorker.OnPretendMerge event. /// </summary> /// <param name="sender">the merge worker</param> /// <param name="e">merge event args</param> public void MergeWorker_OnPretendMerge(object sender, MergeEventArgs e) { _numpkgs++; _dloadsz += e.Distribution.TotalSize; string distrepo = e.Distribution.PortsTree.Repository; if (!_repolst.Contains(distrepo)) _repolst.Add(distrepo); if (e.HardMask) _hardmask.Add(e.Distribution.Atom); if (e.KeywordMask) _kwmask.Add(new Tuple<Atom, string[]>(e.Distribution.Atom, e.KeywordsNeeded)); Console.Write("["); if (e.Selected) Console.ForegroundColor = ConsoleColor.Green; else Console.ForegroundColor = ConsoleColor.DarkGreen; Console.Write("port "); Console.ResetColor(); if (e.Flags.HasFlag(MergeFlags.BlockUnresolved) || e.Flags.HasFlag(MergeFlags.BlockResolved)) { Console.ForegroundColor = ConsoleColor.Red; Console.Write("{0}", e.Flags.HasFlag(MergeFlags.BlockUnresolved) ? "B" : "b"); Console.ResetColor(); } else if (e.Flags.HasFlag(MergeFlags.Interactive)) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("I"); Console.ResetColor(); } else Console.Write(" "); Console.ForegroundColor = ConsoleColor.Green; Console.Write("{0}", e.Flags.HasFlag(MergeFlags.New) ? "N" : " "); Console.ResetColor(); if (e.Flags.HasFlag(MergeFlags.Replacing)) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("R"); Console.ResetColor(); } else if (e.Flags.HasFlag(MergeFlags.Slot)) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("S"); Console.ResetColor(); } else Console.Write(" "); if (e.Flags.HasFlag(MergeFlags.FetchNeeded) || e.Flags.HasFlag(MergeFlags.FetchExists)) { Console.ForegroundColor = ConsoleColor.Red; Console.Write("{0}", e.Flags.HasFlag(MergeFlags.FetchNeeded) ? "F" : "f"); Console.ResetColor(); } else Console.Write(" "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("{0}", e.Flags.HasFlag(MergeFlags.Updating) ? "U" : " "); Console.ResetColor(); Console.ForegroundColor = ConsoleColor.Blue; Console.Write("{0}", e.Flags.HasFlag(MergeFlags.Downgrading) ? "D" : " "); Console.ResetColor(); if (e.HardMask) { Console.ForegroundColor = ConsoleColor.Red; Console.Write("M"); Console.ResetColor(); } else if (e.KeywordMask) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("~"); Console.ResetColor(); } else Console.Write(" "); Console.Write("]"); if (e.Selected) Console.ForegroundColor = ConsoleColor.Green; else Console.ForegroundColor = ConsoleColor.DarkGreen; Console.Write(" {0}", e.Distribution.ToString()); Console.ResetColor(); if (!e.Flags.HasFlag(MergeFlags.New) && !e.Flags.HasFlag(MergeFlags.Replacing)) { Console.ForegroundColor = ConsoleColor.Blue; Console.Write(" [{0}]", e.Previous.Version.ToString()); Console.ResetColor(); } StringBuilder sb = new StringBuilder(11); Win32.StrFormatByteSize(e.Distribution.TotalSize, sb, sb.Capacity); Console.Write(" {0}", sb.ToString()); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write(" [{0}]", _repolst.IndexOf(distrepo)); Console.ResetColor(); Console.Write("\n"); }
/// <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); } }
/// <summary> /// Handler for the MergeWorker.OnInstall event. /// </summary> /// <param name="sender">the merge worker</param> /// <param name="e">merge event args</param> public void MergeWorker_OnInstall(object sender, MergeEventArgs e) { Console.Write("\n>>> Installing "); Console.ForegroundColor = ConsoleColor.Green; Console.Write(e.Distribution.ToString()); Console.ResetColor(); Console.Write(" into live file system\n"); }
/// <summary> /// Merge a single package into the system. /// </summary> /// <param name="mea">merge event arguments</param> /// <param name="mopts">merge options</param> /// <param name="downloader">the downloader</param> /// <param name="rootdir">root directory</param> private void MergeOne(MergeEventArgs mea, MergeOptions mopts, Downloader downloader, DirectoryInfo rootdir) { IDistribution dist = mea.Distribution; uint rc = 0; if (mopts.HasFlag(MergeOptions.Pretend)) { if (this.OnPretendMerge != null) this.OnPretendMerge.Invoke(this, mea); return; } if (this.OnRealMerge != null) this.OnRealMerge.Invoke(this, mea); if (mea.HardMask || mea.KeywordMask) throw new MaskedPackageException(mea.Distribution.Package.FullName); if (dist.PlatformSources.Length > 0) { if (mea.FetchHandle != Guid.Empty && !downloader.Peek(mea.FetchHandle)) { _log.Info("Fetching files in the background... please wait"); _log.InfoFormat("See {0} for fetch progress", downloader.LogFile); downloader.WaitFor(mea.FetchHandle); } _log.InfoFormat("Checking package digests"); foreach (SourceFile src in dist.PlatformSources) { FileInfo distfile = new FileInfo(_cfg.DistFilesDir + @"\" + src.LocalName); if (!Md5Sum.Check(distfile.FullName, src.Digest, Md5Sum.MD5SUMMODE.BINARY)) { _log.ErrorFormat("Digest check failed for {0}", distfile.FullName); throw new InstallException("Computed digest doesn't match expected value."); } } } if (mopts.HasFlag(MergeOptions.FetchOnly)) return; SandboxDirectory sbox = SandboxDirectory.Create(); _log.DebugFormat("Created sandbox directory: {0}", sbox.Root.FullName); IInstallProject installer = dist.GetInstallProject(sbox); if (installer == null) throw new InstallException("Encountered missing or invalid installer project."); bool runmake = installer.HasSrcUnpackTarget || installer.HasSrcCompileTarget || installer.HasSrcInstallTarget || installer.HasSrcTestTarget; if (runmake && (rc = this.SpawnSandboxHost(sbox, installer)) != 0) { _log.DebugFormat("sandbox host return code: {0}", rc); throw new InstallException("Installation failed. See previous errors."); } if (this.OnInstall != null) this.OnInstall.Invoke(this, mea); if (_cfg.CollisionDetect && this.DetectCollisions(sbox.ImageDir, dist.Atom)) throw new InstallException("File collision(s) were detected."); if (mea.Previous != null) { _log.Debug("Trashing files from previous installation"); FileTuple[] oldfiles = _pkgmgr.QueryPackageFiles(mea.Previous); foreach (FileTuple ft in oldfiles) { if (ft.Item2 != FileType.Directory || !this.IsProtected(ft.Item1)) TrashWorker.AddFile(ft.Item1, _pkgmgr); } } FileTuple[] files = null; FileTuple[] shortcuts = null; if (installer.HasPkgPreInstTarget) { _log.Info("Executing pre-install tasks..."); installer.PkgPreInst(); } IntPtr wow64oldval = IntPtr.Zero; if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) { if (!Wow64DisableWow64FsRedirection(out wow64oldval)) throw new InstallException("Failed to disable Wow64 file system redirection."); } try { this.InstallImage(sbox.ImageDir, rootdir, out files); } finally { if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) Wow64RevertWow64FsRedirection(wow64oldval); } this.InstallImage( sbox.LinkDir, new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu)), out shortcuts); FileTuple[] allfiles = files.Union(shortcuts).ToArray(); Dictionary<string, string> metadata = new Dictionary<string, string>(); metadata.Add("repository", dist.PortsTree.Repository); _pkgmgr.RecordPackage(dist, installer, allfiles, metadata.ToArray()); if (installer.HasPkgPostInstTarget) { _log.Info("Executing post-install tasks..."); installer.PkgPostInst(); } if (mea.Selected) { _log.InfoFormat("Recording {0} in world favourites", dist.Package.FullName); _pkgmgr.SelectPackage(dist.Atom); } _log.Debug("Destroying the sandbox..."); sbox.Delete(); }