Ejemplo n.º 1
0
        /// <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();
        }