예제 #1
0
        /// <summary>
        /// Finds the package matching the given atom.
        /// </summary>
        /// <param name="atom">an atom</param>
        /// <returns>the matching package, or NULL if no match is found</returns>
        protected virtual IPackage ResolvePackage(Atom atom)
        {
            ReadOnlyCollection<IPackage> pkglst = this.Packages;
            IPackage pkg = null;

            if (atom.IsFullName) {
                pkg = pkglst
                    .Where(i => i.FullName == atom.PackageName)
                    .SingleOrDefault();
            } else {
                IPackage[] pkgarr = pkglst
                    .Where(i => i.Name == atom.PackageName)
                    .ToArray();

                if (pkgarr.Length == 1)         /* one match found */
                    pkg = pkgarr[0];
                else if (pkgarr.Length > 1)     /* multiple matches found */
                    throw new AmbiguousMatchException(atom.PackageName);
            }

            return pkg;
        }
예제 #2
0
파일: Atom.cs 프로젝트: rcarz/fusion
        /// <summary>
        /// Determines if the given atom matches the constraints of this atom.
        /// </summary>
        /// <param name="left">the atom to compare to</param>
        /// <returns>true on match, false otherwise</returns>
        /// <remarks>
        /// Evaluation uses the input as the left side of the equation and this
        /// instance as the right side.
        /// 
        /// Example:
        ///     "this" is >=foo/bar-123
        ///     "left" is foo/bar-124
        /// 
        ///     foo/bar-124 >= foo/bar-123
        ///    
        /// In this case the match will succeed. If "this" doesn't have a
        /// comparison operator set, then the package names are compared
        /// for equality and version is ignored. The comparison operator for
        /// "left" is always ignored.
        /// 
        /// If either atom doesn't have a version then version matching is
        /// skipped. Slots are only compared if both sides have slots but
        /// no versions.
        /// </remarks>
        public bool Match(Atom left)
        {
            if (this.IsFullName && left.IsFullName && left.PackageName != _pkg)
                return false;
            else if (left.PackagePart != this.PackagePart)
                return false;

            bool lnoverslot = (!left.HasVersion && left.Slot == 0);
            bool rnoverslot = (!this.HasVersion && _slot == 0);

            if (lnoverslot || rnoverslot || _oper == null)
                return true;
            else if (!left.HasVersion || !this.HasVersion) {
                return left.Slot == _slot;
            } else if (_oper == "=" && left.Version == _ver)
                return true;
            else if (_oper == "<" && left.Version < _ver)
                return true;
            else if (_oper == "<=" && left.Version <= _ver)
                return true;
            else if (_oper == ">" && left.Version > _ver)
                return true;
            else if (_oper == ">=" && left.Version >= _ver)
                return true;
            else if (_oper == "!" && left.Version != _ver)
                return true;

            return false;
        }
예제 #3
0
        /// <summary>
        /// Gets all package distributions referenced by the given atom.
        /// </summary>
        /// <param name="atom">the package atom to lookup</param>
        /// <returns>the matching distributions</returns>
        public virtual IDistribution[] LookupAll(Atom atom)
        {
            IPackage pkg = this.ResolvePackage(atom);
            List<IDistribution> results = new List<IDistribution>();

            if (pkg == null)
                throw new PackageNotFoundException(atom.PackageName);

            if (atom.HasVersion || atom.Slot > 0) {        /* find a specific version */
                IDistribution[] matcharr = pkg.Distributions
                    .Where(i => atom.Match(i.Atom))
                    .OrderBy(i => i.Version)
                    .ToArray();
                if (matcharr.Length == 0)
                    throw new DistributionNotFoundException(atom);

                if (atom.Comparison == "=")
                    results.Add(matcharr.SingleOrDefault());
                else {
                    IDistribution[] unmasked = matcharr
                        .Where(i => !i.PortsTree.IsMasked(i))
                        .ToArray();
                    results.AddRange(unmasked.Length > 0 ? unmasked : matcharr);
                }
            } else {                        /* find the best version */
                if (pkg.LatestUnmasked != null)
                    results.Add(pkg.LatestUnmasked);
                else if (pkg.LatestAvailable != null)
                    results.Add(pkg.LatestAvailable);
            }

            if (results.Count == 0)
                throw new DistributionNotFoundException(atom);

            return results.ToArray();
        }
예제 #4
0
 /// <summary>
 /// Gets the package distribution referenced by the given atom.
 /// If multiple distributions match, then the latest version is
 /// returned.
 /// </summary>
 /// <param name="atom">the package atom to lookup</param>
 /// <returns>the matching distribution</returns>
 public virtual IDistribution Lookup(Atom atom)
 {
     return this.LookupAll(atom)
         .OrderBy(i => i.Version)
         .Last();
 }
예제 #5
0
파일: MergeWorker.cs 프로젝트: rcarz/fusion
        /// <summary>
        /// Determines if files in the image directory would collide with existing
        /// files owned by other packages.
        /// </summary>
        /// <param name="imgdir">image directory</param>
        /// <param name="atom">package atom to test</param>
        /// <returns>true if collisions are detected, false otherwise</returns>
        private bool DetectCollisions(DirectoryInfo imgdir, Atom atom)
        {
            int striplev = imgdir.FullName.TrimEnd('\\').Count(i => i == '\\') + 1;
            string[] files = imgdir
                .GetFileSystemInfos("*", SearchOption.AllDirectories)
                .Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
                .Select(i => String.Join("\\", i.FullName.Split('\\').Skip(striplev)))
                .Select(i => _cfg.RootDir.FullName.TrimEnd('\\') + @"\" + i)
                .ToArray();
            string[] collisions = _pkgmgr.CheckFilesOwner(files, atom);
            bool protect = false;

            foreach (string file in collisions)
                _log.ErrorFormat("File '{0}' is already owned by a package", file);

            foreach (string file in files) {
                if (this.IsProtected(file)) {
                    _log.ErrorFormat("File '{0}' is protected by the system profile", file);
                    protect = true;
                }
            }

            return (collisions.Length > 0 || protect);
        }
예제 #6
0
파일: MergeWorker.cs 프로젝트: rcarz/fusion
        /// <summary>
        /// Unmerges the packages matching the given atoms.
        /// </summary>
        /// <param name="atomarr">package atoms for unmerging</param>
        public void Unmerge(Atom[] atomarr)
        {
            foreach (Atom atom in atomarr) {
                UnmergeEventArgs uae = new UnmergeEventArgs();
                uae.Package = atom;

                if (_pkgmgr.IsProtected(atom))
                    throw new ProtectedPackageException(atom.ToString());

                if (this.OnUnmerge != null)
                    this.OnUnmerge.Invoke(this, uae);

                IInstallProject installer = _pkgmgr.GetPackageInstaller(atom);

                if (installer != null && installer.HasPkgPreRmTarget) {
                    _log.Info("Executing pre-removal tasks...");
                    installer.PkgPreRm();
                }

                FileTuple[] files = _pkgmgr.QueryPackageFiles(atom)
                    .OrderByDescending(i => i.Item1)
                    .ToArray();

                IntPtr wow64oldval = IntPtr.Zero;
                if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) {
                    if (!Wow64DisableWow64FsRedirection(out wow64oldval))
                        throw new InstallException("Failed to disable Wow64 file system redirection.");
                }

                foreach (FileTuple ft in files) {
                    try {
                        if (ft.Item2 == FileType.Directory && this.IsProtected(ft.Item1)) {
                            _log.DebugFormat("Skipping protected directory '{0}'", ft.Item1);
                            continue;
                        }

                        if (ft.Item2 == FileType.Directory) {
                            if (Directory.GetFiles(ft.Item1).Length > 0)
                                throw new IOException();

                            Directory.Delete(ft.Item1);
                            _log.InfoFormat("Deleted directory '{0}'", ft.Item1);
                        } else {
                            File.Delete(ft.Item1);
                            _log.InfoFormat("Deleted file '{0}'", ft.Item1);
                        }
                    } catch (DirectoryNotFoundException) {
                        _log.DebugFormat("Skipping non-existant directory '{0}'", ft.Item1);
                    } catch (FileNotFoundException) {
                        _log.DebugFormat("Skipping non-existant file '{0}'", ft.Item1);
                    } catch {
                        TrashWorker.AddFile(ft.Item1, _pkgmgr);
                        _log.WarnFormat("Marked '{0}' for future removal", ft.Item1);
                    }
                }

                if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
                    Wow64RevertWow64FsRedirection(wow64oldval);

                if (installer != null && installer.HasPkgPostRmTarget) {
                    _log.Info("Executing post-removal tasks...");
                    installer.PkgPostRm();
                }

                _pkgmgr.DeletePackage(atom);

                Atom worldatom = Atom.Parse(atom.PackageName, AtomParseOptions.WithoutVersion);
                if (_pkgmgr.FindPackages(worldatom).Length == 0)
                    _pkgmgr.DeselectPackage(worldatom);
            }

            if (this.OnAutoClean != null)
                this.OnAutoClean.Invoke(this, new EventArgs());

            TrashWorker.Purge(_pkgmgr);
        }
예제 #7
0
        /// <summary>
        /// Determines if the given distribution satisfies dependency requirements for
        /// the current graph.
        /// </summary>
        /// <param name="dist">distribution atom to check</param>
        /// <returns>true if satisfies, false otherwise</returns>
        public bool CheckSatisfies(Atom atom)
        {
            if (!_depmap.ContainsKey(atom.PackageName))
                throw new KeyNotFoundException("Package '" + atom.PackageName + "' is not a dependency.");

            /* the given dist satisfies the requirement if it appears in all matches found */
            foreach (Dependency d in _depmap[atom.PackageName]) {
                if (d.Matches.Where(i => atom.Match(d.Atom)).Count() == 0)
                    return false;
            }

            return true;
        }