Beispiel #1
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var    io     = GetIO();
            var    bucket = GetBucket();
            string binary = input.GetArgument("binary");

            if (input.GetOption("list") || string.IsNullOrEmpty(binary))
            {
                OutputList(bucket, io);
                return(ExitCodes.Normal);
            }

            var dispatcher = bucket.GetEventDispatcher();

            if (output.IsNormal)
            {
                output.SetVerbosity(OutputOptions.VerbosityQuiet);
            }

            var scriptEventArgs = new ScriptEventArgs("__exec_command", bucket, io, true, input.GetArgument("args"));

            dispatcher.AddListener("__exec_command", (sender, eventArgs) =>
            {
                if (dispatcher is BEventDispatcher bucketEventDispatcher)
                {
                    bucketEventDispatcher.ExecuteScript(binary, sender, (ScriptEventArgs)eventArgs);
                    return;
                }

                throw new NotSupportedException("The \"exec\" command can be used only when the event system is BucketEventSystem.");
            });

            dispatcher.Dispatch(this, scriptEventArgs);
            return(scriptEventArgs.ExitCode);
        }
Beispiel #2
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            if (input.GetOption("list"))
            {
                return(ListScripts(output));
            }

            string script = input.GetArgument("script");

            if (string.IsNullOrEmpty(script))
            {
                throw new RuntimeException("Missing required argument \"script\"");
            }

            var defiendEvents  = new HashSet <string>(ScriptEvents.GetEvents());
            var disabledScript = script.ToUpper().Replace("-", "_");

            if (!defiendEvents.Contains(script) && defiendEvents.Contains(disabledScript))
            {
                throw new RuntimeException($"Script \"{script}\" cannot be run with this command");
            }

            var bucket          = GetBucket();
            var devMode         = input.GetOption("dev") || !input.GetOption("no-dev");
            var eventDispatcher = bucket.GetEventDispatcher();

            if (!eventDispatcher.HasListener(script))
            {
                throw new RuntimeException($"Script \"{script}\" is not defined in this package");
            }

            string[] args    = input.GetArgument("args");
            string   timeout = input.GetOption("timeout");

            if (timeout != null)
            {
                BucketProcessExecutor.SetDefaultTimeout(int.Parse(timeout));
            }

            var eventArgs = new ScriptEventArgs(script, bucket, GetIO(), devMode, args);

            eventDispatcher.Dispatch(this, eventArgs);
            return(eventArgs.ExitCode);
        }
Beispiel #3
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var bucket = GetBucket(true, input.GetOption("no-plugins"));

            string[] packages = input.GetArgument("packages") ?? Array.Empty <string>();

            packages = ProcessRootRequires(bucket.GetPackage(), input, packages);

            // todo: set no-progress.
            // todo: add gui interactive select the packages.
            var commandEvent = new CommandEventArgs(PluginEvents.Command, "update", input, output);

            bucket.GetEventDispatcher().Dispatch(this, commandEvent);

            var io        = GetIO();
            var installer = new BucketInstaller(io, bucket);

            var config = bucket.GetConfig();

            var(preferSource, preferDist) = GetPreferredInstallOptions(config, input);

            ISet <string> GetUpdateWhitlist()
            {
                if (input.GetOption("lock"))
                {
                    return(new HashSet <string>(new[] { "lock" }));
                }

                return(packages.Empty() ? null : new HashSet <string>(packages));
            }

            installer.SetDryRun(input.GetOption("dry-run"))
            .SetVerbose(input.GetOption("verbose"))
            .SetPreferSource(preferSource)
            .SetPreferDist(preferDist)
            .SetDevMode(!input.GetOption("no-dev"))
            .SetRunScripts(!input.GetOption("no-scripts"))
            .SetSkipSuggest(input.GetOption("no-suggest"))
            .SetIgnorePlatformRequirements(input.GetOption("ignore-platform-reqs"))
            .SetUpdate(true)
            .SetUpdateWhitelist(GetUpdateWhitlist())
            .SetWhitelistAllDependencies(input.GetOption("with-all-dependencies"))
            .SetWhitelistTransitiveDependencies(input.GetOption("with-dependencies"))
            .SetPreferStable(input.GetOption("prefer-stable"))
            .SetPreferLowest(input.GetOption("prefer-lowest"));

            if (input.GetOption("no-plugins"))
            {
                installer.DisablePlugins();
            }

            return(installer.Run());
        }
Beispiel #4
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var io = GetIO();

            string[] args = input.GetArgument("packages");
            if (!args.Empty())
            {
                io.WriteError($"<error>Invalid argument {string.Join(Str.Space, args)}. Use \"bucket require {string.Join(Str.Space, args)}\" instead to add packages to your bucket.json.</error>");
                return(ExitCodes.GeneralException);
            }

            var bucket = GetBucket(true, input.GetOption("no-plugins"));

            // todo: set no-progress.
            var commandEvent = new CommandEventArgs(PluginEvents.Command, "install", input, output);

            bucket.GetEventDispatcher().Dispatch(this, commandEvent);

            var installer = new BucketInstaller(io, bucket);

            var config = bucket.GetConfig();

            var(preferSource, preferDist) = GetPreferredInstallOptions(config, input);

            installer.SetDryRun(input.GetOption("dry-run"))
            .SetVerbose(input.GetOption("verbose"))
            .SetPreferSource(preferSource)
            .SetPreferDist(preferDist)
            .SetDevMode(!input.GetOption("no-dev"))
            .SetRunScripts(!input.GetOption("no-scripts"))
            .SetSkipSuggest(input.GetOption("no-suggest"))
            .SetIgnorePlatformRequirements(input.GetOption("ignore-platform-reqs"));

            if (input.GetOption("no-plugins"))
            {
                installer.DisablePlugins();
            }

            return(installer.Run());
        }
Beispiel #5
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var platformRepository = new RepositoryPlatform();
            var io = GetIO();

            var bucket = GetBucket(false);

            if (!bucket)
            {
                var factory = new Factory();
                bucket = factory.CreateBucket(io, new ConfigBucket(), input.HasRawOption("--no-plugins"));
            }

            var localInstalledRepository = bucket.GetRepositoryManager().GetLocalInstalledRepository();
            var repositoryInstalled      = new RepositoryComposite(localInstalledRepository, platformRepository);
            var repositories             = new RepositoryComposite(Arr.Merge(new[] { repositoryInstalled }, bucket.GetRepositoryManager().GetRepositories()));

            var commandEvent = new CommandEventArgs(PluginEvents.Command, "search", input, output);

            bucket.GetEventDispatcher().Dispatch(this, commandEvent);

            var flags   = input.GetOption("only-name") ? SearchMode.Name : SearchMode.Fulltext;
            var results = repositories.Search(string.Join(Str.Space, input.GetArgument("tokens")), flags, input.GetOption("type"));

            var seed = new HashSet <string>();

            foreach (var result in results)
            {
                if (!seed.Add(result.GetName()))
                {
                    continue;
                }

                io.Write(result.ToString());
            }

            return(ExitCodes.Normal);
        }
Beispiel #6
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var io             = GetIO();
            var versionUtility = new BucketVersions(io, config, transport);

            Channel?storedChannel = null;

            foreach (var channel in new[] { Channel.Stable, Channel.Preview, Channel.Dev })
            {
                // An unstable version will overwrite a stable version.
                if (input.GetOption(channel.ToString().ToLower()))
                {
                    versionUtility.SetChannel(channel);
                    storedChannel = channel;
                }
            }

            if (input.GetOption("set-channel-only"))
            {
                if (storedChannel != null)
                {
                    io.WriteError($"Channel {storedChannel.ToString().ToLower()} has been saved.");
                }
                else
                {
                    io.WriteError($"Channel not stored.");
                }

                return(ExitCodes.Normal);
            }

            if (input.GetOption("update-keys"))
            {
                return(FetchKeys(io, config));
            }

            if (input.GetOption("rollback"))
            {
                return(Rollback(io, installDir, backupDir));
            }

            var(lastedVersion, remoteFileUri, lastedVersionPretty, _) = versionUtility.GetLatest();
            var updateVersion   = input.GetArgument("version") ?? lastedVersion;
            var updatingWithDev = versionUtility.GetChannel() == Channel.Dev;

            // If it is the latest version we end the update.
            if (Bucket.GetVersion() == updateVersion)
            {
                io.WriteError($"<info>You are already using bucket version <comment>{Bucket.GetVersionPretty()}</comment> ({Bucket.GetVersion()},{versionUtility.GetChannel().ToString().ToLower()} channel).</info>");

                CheckCleanupBackups(io, input, backupDir);
                return(ExitCodes.Normal);
            }

            if (string.IsNullOrEmpty(remoteFileUri))
            {
                var remoteRelativePath = updatingWithDev ?
                                         $"/snapshot/{updateVersion}/bucket.zip" :
                                         $"/releases/{updateVersion}/bucket.zip";
                remoteFileUri = $"{baseUri}{remoteRelativePath}";
            }
            else if (!BucketUri.IsAbsoluteUri(remoteFileUri))
            {
                remoteFileUri = new Uri(new Uri(baseUri), remoteFileUri).ToString();
            }

            var tempFile      = Path.Combine(tempDir, Path.GetFileName(remoteFileUri));
            var signatureFile = updatingWithDev ? $"{home}/keys.dev.pem" : $"{home}/keys.tags.pem";

            tempFile = DownloadRemoteFile(io, remoteFileUri, tempFile, signatureFile);

            // Clean up the backup first, so that the current version
            // will be the last version.
            CheckCleanupBackups(io, input, backupDir);

            try
            {
                InstalltionBucket(installDir, tempFile, backupFile);
            }
#pragma warning disable CA1031
            catch (SException ex)
#pragma warning restore CA1031
            {
                fileSystem.Delete(tempFile);
                io.WriteError($"<error>The file is corrupted ({ex.Message}).</error>");
                io.WriteError("<error>Please re-run the self-update command to try again.</error>");
                return(ExitCodes.GeneralException);
            }

            // The version number may be entered by the user.
            if (updateVersion == lastedVersion)
            {
                io.WriteError($"Bucket has been successfully upgraded to: <comment>{Bucket.ParseVersionPretty(lastedVersionPretty)}</comment> ({lastedVersion})");
            }
            else
            {
                io.WriteError($"Bucket has been successfully upgraded to: <comment>{updateVersion}</comment>");
            }

            if (fileSystem.Exists(backupFile, FileSystemOptions.File))
            {
                io.WriteError($"Use <info>bucket self-update --rollback</info> to return to version <comment>{Bucket.GetVersionPretty()}</comment> ({Bucket.GetVersion()})");
            }
            else
            {
                io.WriteError($"<warning>A backup of the current version could not be written to {backupFile}, no rollback possible</warning>");
            }

            return(ExitCodes.Normal);
        }
Beispiel #7
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            string[] packages = input.GetArgument("packages");
            packages = Arr.Map(packages, (package) => package.ToLower());

            var file     = Factory.GetBucketFile();
            var filePath = Path.Combine(Environment.CurrentDirectory, file);

            var jsonFile     = new JsonFile(filePath);
            var configBucket = jsonFile.Read <ConfigBucket>();
            var backup       = File.ReadAllText(filePath);

            var source = new JsonConfigSource(jsonFile);
            var io     = GetIO();

            var requireKey            = input.GetOption("dev") ? LinkType.RequireDev : LinkType.Require;
            var alternativeRequireKey = input.GetOption("dev") ? LinkType.Require : LinkType.RequireDev;

            var requireMapping            = new Dictionary <string, string>();
            var alternativeRequireMapping = new Dictionary <string, string>();

            void EstablishCaseMapping(IDictionary <string, string> mapping, LinkType type)
            {
                var collection = type == LinkType.Require ? configBucket.Requires : configBucket.RequiresDev;

                if (collection == null)
                {
                    return;
                }

                foreach (var item in collection)
                {
                    mapping[item.Key.ToLower()] = item.Key;
                }
            }

            EstablishCaseMapping(requireMapping, requireKey);
            EstablishCaseMapping(alternativeRequireMapping, alternativeRequireKey);

            bool TryGetMatchPackages(IDictionary <string, string> mapping, string package, out IEnumerable <string> matches)
            {
                var result       = new List <string>();
                var regexPackage = BasePackage.PackageNameToRegexPattern(package);

                foreach (var item in mapping)
                {
                    if (Regex.IsMatch(item.Key, regexPackage, RegexOptions.IgnoreCase))
                    {
                        result.Add(item.Value);
                    }
                }

                matches = result;
                return(result.Count > 0);
            }

            foreach (var package in packages)
            {
                if (requireMapping.TryGetValue(package, out string originalName))
                {
                    source.RemoveLink(requireKey, originalName);
                }
                else if (alternativeRequireMapping.TryGetValue(package, out originalName))
                {
                    io.WriteError($"<warning>{originalName} could not be found in {Str.LowerDashes(requireKey.ToString())} but it is present in {Str.LowerDashes(alternativeRequireKey.ToString())}</warning>");
                    if (io.IsInteractive && io.AskConfirmation($"Do you want to remove it from {Str.LowerDashes(alternativeRequireKey.ToString())} [<comment>yes</comment>]? ", true))
                    {
                        source.RemoveLink(alternativeRequireKey, originalName);
                    }
                }
                else if (TryGetMatchPackages(requireMapping, package, out IEnumerable <string> matches))
                {
                    foreach (var match in matches)
                    {
                        source.RemoveLink(requireKey, match);
                    }
                }
                else if (TryGetMatchPackages(alternativeRequireMapping, package, out matches))
                {
                    foreach (var match in matches)
                    {
                        io.WriteError($"<warning>{match} could not be found in {Str.LowerDashes(requireKey.ToString())} but it is present in {Str.LowerDashes(alternativeRequireKey.ToString())}</warning>");
                        if (io.IsInteractive && io.AskConfirmation($"Do you want to remove it from {Str.LowerDashes(alternativeRequireKey.ToString())} [<comment>yes</comment>]? ", true))
                        {
                            source.RemoveLink(alternativeRequireKey, match);
                        }
                    }
                }
                else
                {
                    io.WriteError($"<warning>{package} is not required in your bucket.json and has not been removed</warning>");
                }
            }

            if (input.GetOption("no-update"))
            {
                return(ExitCodes.Normal);
            }

            // todo: implement installer uninstall.
            ResetBucket();

            var bucket = GetBucket(true, input.GetOption("no-plugins"));

            // todo: set no-progress.
            var commandEvent = new CommandEventArgs(PluginEvents.Command, "remove", input, output);

            bucket.GetEventDispatcher().Dispatch(this, commandEvent);

            ISet <string> GetRemoveWhitlist()
            {
                Guard.Requires <UnexpectedException>(packages.Length > 0);
                return(new HashSet <string>(packages));
            }

            var installer = new BucketInstaller(io, bucket);
            var status    = installer
                            .SetVerbose(input.GetOption("verbose"))
                            .SetDevMode(!input.GetOption("update-no-dev"))
                            .SetRunScripts(!input.GetOption("no-scripts"))
                            .SetUpdate(true)
                            .SetUpdateWhitelist(GetRemoveWhitlist())
                            .SetWhitelistTransitiveDependencies(!input.GetOption("no-update-with-dependencies"))
                            .SetIgnorePlatformRequirements(input.GetOption("ignore-platform-reqs"))
                            .Run();

            if (status != 0)
            {
                io.WriteError($"{Environment.NewLine}<error>Removal failed, reverting {file} to its original content.</error>");
                File.WriteAllText(filePath, backup);
            }

            return(status);
        }
Beispiel #8
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            var file       = input.GetArgument("file") ?? Factory.GetBucketFile();
            var io         = GetIO();
            var fileSystem = new FileSystemLocal();

            if (!fileSystem.Exists(file))
            {
                io.WriteError($"<error>{file} not found.</error>");
                return(ExitCodes.FileNotFoundException);
            }

            var checkPublish = !input.GetOption("no-check-publish");
            var checkLock    = !input.GetOption("no-check-lock");
            var isStrict     = input.GetOption("strict");

            var validator = new ValidatorBucket(fileSystem, io);

            var(warnings, publishErrors, errors) = validator.Validate(file);

            var lockErrors = Array.Empty <string>();
            var bucket     = Factory.Create(io, file, input.HasRawOption("--no-plugins"));
            var locker     = bucket.GetLocker();

            if (locker.IsLocked() && !locker.IsFresh())
            {
                lockErrors = new[] { "The lock file is not up to date with the latest changes in bucket.json, it is recommended that you run `bucket update`." };
            }

            OuputResult(file, ref errors, ref warnings, checkPublish, publishErrors, checkLock, lockErrors, isStrict);

            int GetStrictExitCode()
            {
                return((isStrict && !warnings.Empty()) ? ExitCodes.ValidationWarning : GameBox.Console.ExitCodes.Normal);
            }

            var exitCode = errors.Length > 0 ? ExitCodes.ValidationErrors : GetStrictExitCode();

            if (input.GetOption("with-dependencies"))
            {
                var localInstalledRepository = bucket.GetRepositoryManager().GetLocalInstalledRepository();
                foreach (var package in localInstalledRepository.GetPackages())
                {
                    var path = bucket.GetInstallationManager().GetInstalledPath(package);
                    file = Path.Combine(path, "bucket.json");

                    if (!Directory.Exists(path) || !File.Exists(file))
                    {
                        continue;
                    }

                    (warnings, publishErrors, errors) = validator.Validate(file);
                    OuputResult(file, ref errors, ref warnings, checkPublish, publishErrors, isStrict: isStrict);

                    var depCode = !errors.Empty() ? ExitCodes.ValidationErrors : GetStrictExitCode();
                    exitCode = Math.Max(depCode, exitCode);
                }
            }

            var commandEvent = new CommandEventArgs(PluginEvents.Command, "validate", input, output);

            bucket.GetEventDispatcher().Dispatch(this, commandEvent);

            return(Math.Max(exitCode, commandEvent.ExitCode));
        }
Beispiel #9
0
        /// <inheritdoc />
        protected override int Execute(IInput input, IOutput output)
        {
            file     = Factory.GetBucketFile();
            filePath = Path.Combine(Environment.CurrentDirectory, file);
            var io = GetIO();

            newlyCreated = !File.Exists(filePath);

            if (newlyCreated)
            {
                try
                {
                    File.WriteAllText(filePath, NewBucketContent);
                }
#pragma warning disable CA1031
                catch (SException ex)
#pragma warning restore CA1031
                {
                    io.WriteError($"<error>{file} could not be created: {ex.Message}.</error>");
                    return(ExitCodes.GeneralException);
                }
            }

            backup = File.ReadAllText(filePath);
            if (string.IsNullOrEmpty(backup))
            {
                File.WriteAllText(filePath, NewBucketContent);
                backup = NewBucketContent;
            }

            json = new JsonFile(filePath);

            var bucket = GetBucket(true, input.GetOption("no-plugins"));

            // todo: import mock platform
            repository = new RepositoryComposite(
                Arr.Merge(
                    new[] { new RepositoryPlatform(bucket.GetPackage().GetPlatforms()) },
                    bucket.GetRepositoryManager().GetRepositories()));

            var preferredStability = Stabilities.Stable;
            var preferredStable    = bucket.GetPackage().IsPreferStable ?? false;
            if (!preferredStable)
            {
                preferredStability = bucket.GetPackage().GetMinimumStability() ?? preferredStability;
            }

            var requireKey = input.GetOption("dev") ? LinkType.RequireDev : LinkType.Require;
            var removeKey  = input.GetOption("dev") ? LinkType.Require : LinkType.RequireDev;

            var requirements = FormatRequirements(
                DetermineRequirements(input, output, input.GetArgument("packages"), preferredStability, !input.GetOption("no-update")));

            // validate requirements format.
            var versionParser = new BVersionParser();
            foreach (var item in requirements)
            {
                var package    = item.Key;
                var constraint = item.Value;
                if (package.ToLower() == bucket.GetPackage().GetName())
                {
                    io.WriteError($"<error>Root package \"{package}\" cannot require itself in its bucket.json</error>");
                    return(ExitCodes.Normal);
                }

                versionParser.ParseConstraints(constraint);
            }

            var sortPackages = input.GetOption("sort-packages") || bucket.GetConfig().Get(Settings.SortPackages);

            if (!UpdateFileCleanly(json, requirements, requireKey, removeKey, sortPackages))
            {
                File.WriteAllText(filePath, backup);
                throw new RuntimeException("Failed to write to file successfully, operation has been rolled back.");
            }

            io.WriteError($"<info>{file} has been {(newlyCreated ? "created" : "update")}</info>");

            if (input.GetOption("no-update"))
            {
                return(ExitCodes.Normal);
            }

            try
            {
                return(DoUpdate(input, output, io, requirements));
            }
            catch (SException)
            {
                RevertBucketFile(false);
                throw;
            }
        }