示例#1
0
        /// <summary>
        /// Install the given packages in the correct order to avoid missing dependencies
        /// </summary>
        /// <param name="packages">The list of packages with their dependencies</param>
        /// <returns>A response object that contains the status of the install and a comma separated string of package names in the order of install, such that a package's dependency will always precede that package</returns>
        public static PackageInstallResponse InstallPackages(string[] packages)
        {
            PackageInstallResponse response = new PackageInstallResponse();

            try
            {
                // Parse packages to a list of PackageInfo objects
                List <PackageInfo> packageInfoList = GetPackageInfoList(packages);

                List <PackageInfo> installedPackages = new List <PackageInfo>();

                // Get and install the packages with no dependencies first
                List <PackageInfo> installQueue = packageInfoList.Where(x => x.Dependency == string.Empty).ToList();

                // Filter the packages to exclude the ones with no dependencies
                packageInfoList = packageInfoList.Where(x => x.Dependency != string.Empty).ToList();

                // Perform a topological sort, while the install queue is not empty
                while (installQueue.Count > 0)
                {
                    // Remove the first package from the install queue, and install the package
                    PackageInfo currPackage = installQueue.First();
                    installQueue.Remove(currPackage);
                    installedPackages.Add(currPackage);

                    // Find all packages that have a dependency on the current package and add them to the install queue
                    List <PackageInfo> packagesWithCurrentDependency = packageInfoList.Where(x => x.Dependency == currPackage.Name).ToList();
                    foreach (PackageInfo package in packagesWithCurrentDependency)
                    {
                        // We are handling the package, so remove it from the original "graph" i.e. packageInfoList
                        packageInfoList.Remove(package);

                        // Because packages only have one dependency, we know the current package dependencies are already installed, so just add this to the install queue
                        installQueue.Add(package);
                    }
                }

                // If there are still items in the original list, the package dependencies contain a cycle or a dependency on a missing package
                if (packageInfoList.Count > 0)
                {
                    response.Status = PackageInstallStatuses.CONTAINS_CYCLE;
                }
                else
                {
                    // The package dependencies did not contain a cycle, get the formatted string of the install order
                    string installedPackagesFormatted = GetInstalledPackagesFormatted(installedPackages);

                    response.Status            = PackageInstallStatuses.SUCCESS;
                    response.InstalledPackages = installedPackagesFormatted;
                }
            }
            catch
            {
                // If given incorrectly formatted input, we will break here and just return an error status
                response.Status = PackageInstallStatuses.ERROR;
            }

            return(response);
        }
        public void TestInstallPackagesInvalid_Easy()
        {
            string[] input = new string[]
            {
                "KittenService: ",
                "Leetmeme: Cyberportal",
            };

            PackageInstallResponse response = PackageInstallService.InstallPackages(input);

            // The response should never be null
            Assert.AreNotEqual(null, response);

            // This should report that it contains a package with a dependency on a missing package and no packages should be installed
            Assert.AreEqual(PackageInstallStatuses.CONTAINS_CYCLE, response.Status);
            Assert.AreEqual(string.Empty, response.InstalledPackages);
        }
        public void TestInstallPackagesValid_Easy()
        {
            string[] input = new string[]
            {
                "KittenService: CamelCaser",
                "CamelCaser: "
            };

            PackageInstallResponse response = PackageInstallService.InstallPackages(input);

            // The response should never be null
            Assert.AreNotEqual(null, response);

            // The response should be successful with this result
            Assert.AreEqual(PackageInstallStatuses.SUCCESS, response.Status);
            Assert.AreEqual("CamelCaser, KittenService", response.InstalledPackages);
        }
        public void TestInstallPackagesInvalid_Medium()
        {
            string[] input = new string[]
            {
                "KittenService: ",
                "Leetmeme: Cyberportal",
                "Cyberportal: Ice",
                "CamelCaser: KittenService",
                "Fraudstream: ",
                "Ice: Leetmeme"
            };

            PackageInstallResponse response = PackageInstallService.InstallPackages(input);

            // The response should never be null
            Assert.AreNotEqual(null, response);

            // This should report that it contains a cycle and no packages should be installed
            Assert.AreEqual(PackageInstallStatuses.CONTAINS_CYCLE, response.Status);
            Assert.AreEqual(string.Empty, response.InstalledPackages);
        }
        public void TestInstallPackagesValid_Hard()
        {
            string[] input = new string[]
            {
                "Texture: Cabbage",
                "Bread: Amusement",
                "Cabbage: Giraffe",
                "Amusement: Giraffe",
                "Giraffe: Flower",
                "Flower: "
            };

            PackageInstallResponse response = PackageInstallService.InstallPackages(input);

            // The response should never be null
            Assert.AreNotEqual(null, response);

            // The response should be successful with this result
            Assert.AreEqual(PackageInstallStatuses.SUCCESS, response.Status);
            Assert.AreEqual("Flower, Giraffe, Cabbage, Amusement, Texture, Bread", response.InstalledPackages);
        }
        public void TestInstallPackagesValid_Medium()
        {
            string[] input = new string[]
            {
                "KittenService: ",
                "Leetmeme: Cyberportal",
                "Cyberportal: Ice",
                "CamelCaser: KittenService",
                "Fraudstream: Leetmeme",
                "Ice: "
            };

            PackageInstallResponse response = PackageInstallService.InstallPackages(input);

            // The response should never be null
            Assert.AreNotEqual(null, response);

            // The response should be successful with this result
            Assert.AreEqual(PackageInstallStatuses.SUCCESS, response.Status);
            Assert.AreEqual("KittenService, Ice, CamelCaser, Cyberportal, Leetmeme, Fraudstream", response.InstalledPackages);
        }
示例#7
0
        static void Main(string[] args)
        {
            // Allow package input as arguments or wait for it in the program
            string[] packages = args;
            if (args.Length == 0)
            {
                try
                {
                    /*
                     * Accepts input in any of the following formats:
                     *      [ "PackageName: Dependency", "PackageName: " ]
                     *      "PackageName: Dependency", "PackageName: "
                     *      PackageName: Dependency, PackageName:
                     */
                    string input = Console.ReadLine();

                    packages = PackageInstallService.GetCleanedPackageListFromInput(input);
                }
                catch
                {
                    Console.WriteLine("Invalid input given, exiting program");

                    return;
                }
            }

            // Exit the program if no valid input was given.
            if (packages.Length == 0)
            {
                Console.WriteLine("There is nothing to install, exiting program");

                return;
            }

            // Install the given packages based on their dependencies
            PackageInstallResponse response = PackageInstallService.InstallPackages(packages);

            // Build a message based on the result of the install
            string message = string.Empty;

            switch (response.Status)
            {
            case PackageInstallStatuses.SUCCESS:
            {
                message = response.InstalledPackages;
                break;
            }

            case PackageInstallStatuses.CONTAINS_CYCLE:
            {
                message = "No Packages were installed, invalid dependency specification that contains cycles or a dependency on a missing package.";
                break;
            }

            case PackageInstallStatuses.ERROR:
            case PackageInstallStatuses.DEFAULT_NOT_SET:
            default:
            {
                message = "No Packages were installed, unknown error occurred.";
                break;
            }
            }

            // Print the result to the console
            Console.WriteLine(message);
        }