
Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.
History is littered with hundreds of conflicts over the future of a community, group, location or business that were "resolved" when one of the parties stepped ahead and destroyed what was there. With the original point of contention destroyed, the debates would fall to the wayside. Archive Team believes that by duplicated condemned data, the conversation and debate can continue, as well as the richness and insight gained by keeping the materials. Our projects have ranged in size from a single volunteer downloading the data to a small-but-critical site, to over 100 volunteers stepping forward to acquire terabytes of user-created data to save for future generations.
The main site for Archive Team is at archiveteam.org and contains up to the date information on various projects, manifestos, plans and walkthroughs.
This collection contains the output of many Archive Team projects, both ongoing and completed. Thanks to the generous providing of disk space by the Internet Archive, multi-terabyte datasets can be made available, as well as in use by the Wayback Machine, providing a path back to lost websites and work.
Our collection has grown to the point of having sub-collections for the type of data we acquire. If you are seeking to browse the contents of these collections, the Wayback Machine is the best first stop. Otherwise, you are free to dig into the stacks to see what you may find.
The Archive Team Panic Downloads are full pulldowns of currently extant websites, meant to serve as emergency backups for needed sites that are in danger of closing, or which will be missed dearly if suddenly lost due to hard drive crashes or server failures.
There are several important issues in the PowerShell language that cannot be corrected without introducing breaking changes. At the same time, the number of breaking changes introduced in a new version of PowerShell needs to be as minimal as possible, so that there is a low barrier to adoption of new versions, allowing community members to transition scripts and modules across versions more easily. Given that those two statements are in conflict with one another, we need to consider how we can optionally introduce breaking changes into PowerShell over time.
PowerShell has support for experimental features, which some may think covers this need; however, the intent of experimental features is to allow the community to try pre-release versions of PowerShell with breaking changes that are deemed necessary or new features that are not necessarily fully tested/polished so that they can more accurately assess the impact of those features. For release versions of PowerShell, an experimental feature has one of three possible outcomes:
In some cases a breaking change may be implemented immediately as an optional feature, when it is known up front that such a breaking change would be considered harmful to adoption of new versions of PowerShell if it was in place by default yet is still found important enough to implement as an optional feature.
Given all of that, we need to add support for optional features in PowerShell so that what is described above becomes a reality.
As an example of a feature that will be optional if implemented, see the RFC proposal to allow execution preferences to persist beyond module or script scope or the RFC proposal to make terminating errors terminate the right way in PowerShell.
Motivation
As a script, function, or module author,
I can enable optional features for specific users or in specific scopes,
So that I can leverage important new functionality that includes breaking changes in my code without risk of breaking other scripts, functions or modules.
User experience
Specification
Unlike experimental features, which can only be enabled or disabled in PowerShell sessions created after enabling or disabling them, optional features can be enabled or disabled in the current PowerShell session as well as in future PowerShell sessions. This is necessary to allow certain functionality to be "lit up" in packaged modules or scripts.
Below you will find details describing how this functionality will be implemented.
System and User powershell.config.json configuration files
Enabling optional features automatically in future PowerShell sessions requires creating or updating one of two
powershell.config.jsonconfiguration files that are read on startup of a new PowerShell session:$PSHOME, which applies to all user sessions$HOME\Documents\PowerShell\powershell.config.jsonon Windows or$HOME/.config/powershell/powershell.config.jsonon Linux and macOS, which applies only to current user sessions.This RFC will enable optional feature defaults to be read from these configuration files, with current user configuration taking precedence over system (all users) configuration. System config is not policy so this should be acceptable and expected.
Add parameter to New-ModuleManifest
[-OptionalFeatures <object[]>]This parameter would configure specific optional features in the new module manifest that is generated.
The values provided to this parameter would be combined with optional features that are enabled or disabled by default according to the session configuration files, with the values specified in the
New-ModuleManifestcommand overriding the settings for optional features with the same name that are configured in the configuration files. Entries in this collection would either be string (the name of the optional feature to enable) or a hashtable with two keys:name(a string) andenabled(a boolean value). The hashtable allows an optional feature to be specifically disabled instead of enabled within a module, which is necessary if an older module does not support a newer optional feature yet.A terminating error is generated if the same optional feature name is used twice in the collection passed into the
-OptionalFeaturesparameter.Add parameter set to #requires statement
#requires -OptionalFeatures <string[]> [-Disabled]This parameter set would enable, or disable if
-Disabledis used, optional features identified by-Namein the current script file.New command: Get-OptionalFeatureConfiguration
This command would return the current configuration of optional features that are available in PowerShell, read from the configuration files.
The properties on the
S.M.A.OptionalFeatureConfigurationobject would beName,Session,NewManifest, andFor, defined as follows:NameSessionNewManifestForCurrentUserorAllUsersThe default output format is of type table with the properties
Name,Session, andNewManifestwith the results grouped byFor.When this command is invoked with the
-Forparameter, the results are automatically filtered for that configuration file. The default value for-Foris both flags, showing configuration values from both configuration files.New command: Get-OptionalFeature
This command will return a list of the optional features that are available in PowerShell, along with their source and description.
The properties on the
S.M.A.OptionalFeatureobject would beName,Source,Description, defined as follows:NameSourceDescriptionThe default output format would be of type table with the properties
Name,Source, andDescription.Enabling and disabling optional features in current and future PowerShell sessions
It is important to note up front that there are three default states for an optional feature: enabled by default, implicitly disabled by default, and explicitly disabled by default. The only time an optional feature needs to be explicitly disabled by default is if it is enabled by default in the AllUsers configuration file and a specific user wants to disable it for their sessions. This impacts how
Disable-OptionalFeatureworks.The
Enable-OptionalFeaturecommand will enable an optional feature in current and future PowerShell sessions either globally (if the-InNewModuleManifestsswitch is not used) or only in manifests created byNew-ModuleManifest.The
Disable-OptionalFeaturecommand will disable an optional feature in current and future PowerShell sessions either globally (if the-InNewModuleManifestsswitch is not used) or only in manifests created byNew-ModuleManifest. If the feature is being disabled forAllUsersand the optional feature is completely disabled in that configuration file as a result of this command, the entry is removed from the configuration file. If the feature is being disabled forAllUsersand there is no entry in the system (all users) configuration file, nothing happens. If the feature is being disabled for theCurrentUserthere is no entry in the system (all users) or current user configuration files, nothing happens. If the feature is being disabled for theCurrentUserand the optional feature is enabled in theAllUsersconfiguration file, users will be informed that this feature is enabled for all users and asked to confirm that they want to explicitly disable this feature for the current user in the current and future PowerShell sessions. They can always re-enable it later.New command: Use-OptionalFeature
This command would enable or disable the optional features whose names are identified in the
-Enableand-Disableparameters for the duration of theScriptBlockidentified in the-ScriptBlockparameter, and return the features to their previous state afterwards. This allows for easy use of optional features over a small section of code. If neither-Enableor-Disableare used, a terminating error is thrown.Checking optional feature states within the PowerShell runtime
Optional features can be enabled or disabled in a session, module, script, or script block. Since enabling or disabling an optional feature can happen at different levels, the current state of an optional feature should be maintained in a stack, where the validation logic simply peeks at the top of the stack to see if the feature is enabled or not, popping the top of the stack off when appropriate (when leaving the scope of the module, script, or script block where the feature is enabled).
Alternate proposals and considerations
Extend experimental features to support the enhancements defined in this RFC
At a glance, experimental features and optional features are very similar to one another, so it was proposed that it may make sense to have them both use the same functionality when it comes to enabling/disabling them in scripts and modules; however, experimental features have a completely different intent (to try out new functionality in a PowerShell session), are only for future PowerShell sessions, and they only have a single on/off state. On the other hand, optional features are for the current and future PowerShell sessions, for the current user or all users, and may be enabled or disabled in various scopes within those sessions. For that reason, this approach doesn't seem like a viable solution. If we want to change that, perhaps someone should file an RFC against experimental features to make that change.
Enable/disable optional features in jobs according to their current state when the job is launched
Jobs run in the background have their own session, and therefore will not automatically have optional features enabled or disabled according to the current state when the job is launched. We should consider updating how jobs are launched in the engine such that they do "inherit" optional feature configuration to allow them to use optional features without additional code.
You might think that you can accomplish this using
#requiresin a script block launched as a job, but that doesn't work -- the#requiresstatement is ignored when you do this at the moment. For example, the see the results of the following script when launched from PowerShell Core:The result of that command shows that the version of PowerShell where the job was run was Core, not Desktop, yet the job ran anyway despite the
#requiresstatement. This may be a bug. If it is, and if that bug is corrected, then you could use #requires to enable/disable features, but regardless it would still be preferable (and more intuitive) for jobs to "inherit" the current optional feature configuration when they are invoked. This includes jobs launched withStart-Job,Start-ThreadJob, the&background operator, parallelizedforeachstatements orForEach-Objectcommands, or the generic-AsJobparameter.