Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,31 @@ WP-CLI `packages/local/` directory.
Specify a destination directory for the command. Defaults to WP-CLI's `packages/local/` directory.

[--license=<license>]
License for the package.
License for the package by SPDX code.
---
default: MIT
options:
- MIT
- Apache-2.0
- BSD-3-Clause
- BSD-2-Clause
- GPL-2.0-only
- GPL-3.0-only
- ISC
- LGPL-3.0-only
- LGPL-2.1-only
- 0BSD
- AGPL-3.0-only
- MPL-2.0
- AFL-3.0
- MS-PL
- BSD-1-Clause
- MIT-0
- CPL-1.0
- BSL-1.0
- Unlicense
- CC0-1.0
- none
Comment thread
ara303 marked this conversation as resolved.
---

[--require_wp_cli=<version>]
Expand Down Expand Up @@ -279,9 +301,30 @@ In this example:
Name of default branch of the underlying repository. Defaults to main.

[--license=<license>]
License for the package.
License for the package by SPDX code.
---
default: MIT
options:
- MIT
- Apache-2.0
- BSD-3-Clause
- BSD-2-Clause
- GPL-2.0-only
- GPL-3.0-only
- ISC
- LGPL-3.0-only
- LGPL-2.1-only
- 0BSD
- AGPL-3.0-only
- MPL-2.0
- AFL-3.0
- MS-PL
- BSD-1-Clause
- MIT-0
- CPL-1.0
- BSL-1.0
- Unlicense
- CC0-1.0
- none
---


Expand Down
52 changes: 52 additions & 0 deletions features/scaffold-package-readme.feature
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,55 @@ Feature: Scaffold a README.md file for an existing package
Then the foo/README.md file should exist
And the contents of the foo/README.md file should match /\t\tShow extended version information/
And the contents of the foo/README.md file should match /\t\tNote: to retrieve/

Scenario: Scaffold a README.md and generate a non-MIT license
Given an empty directory
And a foo/composer.json file:
"""
{
"name": "wp-cli/foo",
"description": "A test package.",
"license": "MIT",
"require": {
"wp-cli/wp-cli": "^2.13"
}
}
"""

When I run `wp scaffold package-readme foo --license=GPL-2.0-only`
Then the foo/README.md file should exist
And the foo/LICENSE file should exist
And the foo/LICENSE file should contain:
"""
GNU GENERAL PUBLIC LICENSE
"""
And the foo/composer.json file should contain:
"""
"license": "GPL-2.0-only"
"""

Scenario: Scaffold a README.md with --license=none removes LICENSE and sets proprietary
Given an empty directory
And a foo/composer.json file:
"""
{
"name": "wp-cli/foo",
"description": "A test package.",
"license": "MIT",
"require": {
"wp-cli/wp-cli": "^2.13"
}
}
"""
And a foo/LICENSE file:
"""
Some existing license content.
"""

When I run `wp scaffold package-readme foo --license=none`
Then the foo/README.md file should exist
And the foo/LICENSE file should not exist
And the foo/composer.json file should contain:
"""
"license": "proprietary"
"""
42 changes: 40 additions & 2 deletions features/scaffold-package.feature
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ Feature: Scaffold WP-CLI commands
And the {PACKAGE_PATH}/local/wp-cli/foo/LICENSE file should exist
And the {PACKAGE_PATH}/local/wp-cli/foo/LICENSE file should contain:
"""
The MIT License (MIT)
MIT License
"""
And the {PACKAGE_PATH}/local/wp-cli/foo/LICENSE file should contain:
"""
wp-cli/foo Contributors
wp-cli/foo
"""
And the {PACKAGE_PATH}/local/wp-cli/foo/wp-cli.yml file should exist
And the {PACKAGE_PATH}/local/wp-cli/foo/.travis.yml file should not exist
Expand Down Expand Up @@ -320,3 +320,41 @@ Feature: Scaffold WP-CLI commands
"""
https://getcomposer.org/doc/01-basic-usage.md#autoloading
"""

Scenario: Scaffold a WP-CLI package with Apache-2.0 license
Given an empty directory

When I run `wp package path`
Then save STDOUT as {PACKAGE_PATH}

When I run `wp scaffold package wp-cli/apache-pkg --skip-tests --skip-github --skip-install --skip-readme --license=Apache-2.0`
Then STDOUT should contain:
"""
Success: Created package files
"""
And the {PACKAGE_PATH}/local/wp-cli/apache-pkg/LICENSE file should exist
And the {PACKAGE_PATH}/local/wp-cli/apache-pkg/LICENSE file should contain:
"""
Apache License
"""
And the {PACKAGE_PATH}/local/wp-cli/apache-pkg/composer.json file should contain:
"""
"license": "Apache-2.0",
"""

Scenario: Scaffold a WP-CLI package with no license
Given an empty directory

When I run `wp package path`
Then save STDOUT as {PACKAGE_PATH}

When I run `wp scaffold package wp-cli/no-license --skip-tests --skip-github --skip-install --skip-readme --license=none`
Then STDOUT should contain:
"""
Success: Created package files
"""
And the {PACKAGE_PATH}/local/wp-cli/no-license/LICENSE file should not exist
And the {PACKAGE_PATH}/local/wp-cli/no-license/composer.json file should contain:
"""
"license": "proprietary",
"""
119 changes: 112 additions & 7 deletions src/ScaffoldPackageCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use WP_CLI\Path;

/**
* @phpstan-type ComposerConfig array{name: string, description: string, extra: array{readme: array{shields: array<string>}, commands: array<string>}, require: array<string, string>, 'require-dev': array<string, string>}
* @phpstan-type ComposerConfig array{name: string, description: string, license?: string, extra: array{readme: array{shields: array<string>}, commands: array<string>}, require: array<string, string>, 'require-dev': array<string, string>}
*/
class ScaffoldPackageCommand {

Expand Down Expand Up @@ -40,9 +40,31 @@ class ScaffoldPackageCommand {
* : Specify a destination directory for the command. Defaults to WP-CLI's `packages/local/` directory.
*
* [--license=<license>]
* : License for the package.
* : License for the package by SPDX code.
* ---
* default: MIT
* options:
* - MIT
* - Apache-2.0
* - BSD-3-Clause
* - BSD-2-Clause
* - GPL-2.0-only
* - GPL-3.0-only
* - ISC
* - LGPL-3.0-only
* - LGPL-2.1-only
* - 0BSD
* - AGPL-3.0-only
* - MPL-2.0
* - AFL-3.0
* - MS-PL
* - BSD-1-Clause
* - MIT-0
* - CPL-1.0
* - BSL-1.0
* - Unlicense
* - CC0-1.0
* - none
Comment thread
ara303 marked this conversation as resolved.
* ---
*
* [--require_wp_cli=<version>]
Expand Down Expand Up @@ -84,6 +106,13 @@ public function package( $args, $assoc_args ) {
$assoc_args['name'] = $args[0];
$assoc_args['year'] = gmdate( 'Y' );

$license_input = Utils\get_flag_value( $assoc_args, 'license', 'MIT' );
if ( 'none' === strtolower( $license_input ) ) {
$assoc_args['license'] = 'proprietary';
Comment thread
ara303 marked this conversation as resolved.
} else {
$assoc_args['license'] = $license_input;
}

$bits = explode( '/', $assoc_args['name'] );
if ( 2 !== count( $bits ) || empty( $bits[0] ) || empty( $bits[1] ) ) {
WP_CLI::error( "'{$assoc_args['name']}' is an invalid package name. Package scaffold expects '<author>/<package>'." );
Expand Down Expand Up @@ -134,7 +163,7 @@ public function package( $args, $assoc_args ) {
"{$package_dir}/.distignore" => file_get_contents( "{$package_root}/.distignore" ),
"{$package_dir}/phpcs.xml.dist" => Utils\mustache_render( "{$template_path}/phpcs.xml.dist.mustache", $assoc_args ),
"{$package_dir}/CONTRIBUTING.md" => file_get_contents( "{$package_root}/CONTRIBUTING.md" ),
"{$package_dir}/LICENSE" => Utils\mustache_render( "{$template_path}/LICENSE.mustache", $assoc_args ),

"{$package_dir}/wp-cli.yml" => $wp_cli_yml,
"{$package_dir}/hello-world-command.php" => Utils\mustache_render( "{$template_path}/hello-world-command.mustache", $assoc_args ),
"{$package_dir}/src/HelloWorldCommand.php" => Utils\mustache_render( "{$template_path}/HelloWorldCommand.mustache", $assoc_args ),
Expand Down Expand Up @@ -166,7 +195,15 @@ public function package( $args, $assoc_args ) {
}

if ( ! Utils\get_flag_value( $assoc_args, 'skip-readme' ) ) {
WP_CLI::runcommand( "scaffold package-readme {$quoted_package_dir} {$force_flag}", array( 'launch' => false ) );
WP_CLI::runcommand( "scaffold package-readme {$quoted_package_dir} {$force_flag} --license={$license_input}", array( 'launch' => false ) );
} elseif ( 'none' !== strtolower( $license_input ) ) {
$license_file_path = $this->resolve_license_file_path( $license_input, $template_path );
if ( null !== $license_file_path ) {
$this->create_files(
[ "{$package_dir}/LICENSE" => Utils\mustache_render( $license_file_path, $assoc_args ) ],
$force
);
}
}

// Display next steps guidance for users.
Expand Down Expand Up @@ -263,9 +300,30 @@ public function package( $args, $assoc_args ) {
* : Name of default branch of the underlying repository. Defaults to main.
*
* [--license=<license>]
* : License for the package.
* : License for the package by SPDX code.
* ---
* default: MIT
* options:
* - MIT
* - Apache-2.0
* - BSD-3-Clause
* - BSD-2-Clause
* - GPL-2.0-only
* - GPL-3.0-only
* - ISC
* - LGPL-3.0-only
* - LGPL-2.1-only
* - 0BSD
* - AGPL-3.0-only
* - MPL-2.0
* - AFL-3.0
* - MS-PL
* - BSD-1-Clause
* - MIT-0
* - CPL-1.0
* - BSL-1.0
* - Unlicense
* - CC0-1.0
* - none
* ---
*
* @when before_wp_load
Expand All @@ -291,6 +349,12 @@ public function package_readme( $args, $assoc_args ) {
$package_root = dirname( __DIR__ );
$template_path = $package_root . '/templates/';

$license_input = Utils\get_flag_value( $assoc_args, 'license' );
if ( null === $license_input ) {
$license_input = isset( $composer_obj['license'] ) ? $composer_obj['license'] : 'MIT';
}
$composer_license = 'none' === strtolower( $license_input ) ? 'proprietary' : $license_input;

Comment thread
ara303 marked this conversation as resolved.
$bits = explode( '/', $composer_obj['name'] );
$readme_args = [
'package_name' => $composer_obj['name'],
Expand All @@ -303,7 +367,7 @@ public function package_readme( $args, $assoc_args ) {
'has_commands' => false,
'wp_cli_update_to_instructions' => 'the latest stable release with `wp cli update`',
'show_powered_by' => isset( $composer_obj['extra']['readme']['show_powered_by'] ) ? (bool) $composer_obj['extra']['readme']['show_powered_by'] : true,
'license' => $assoc_args['license'],
'license' => $composer_license,
];

if ( isset( $composer_obj['extra']['readme']['shields'] ) ) {
Expand Down Expand Up @@ -538,6 +602,35 @@ public function package_readme( $args, $assoc_args ) {
} else {
WP_CLI::success( 'Created package readme.' );
}

// Only write to composer.json if the license has changed. This protects package_readme from
// overwriting files changed by package. Only when --license changes do we need to write.
$existing_license = isset( $composer_obj['license'] ) ? $composer_obj['license'] : '';
$composer_obj['license'] = $composer_license;
if ( $composer_license !== $existing_license ) {
$composer_json_content = json_encode( $composer_obj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . "\n";
if ( false === file_put_contents( $package_dir . '/composer.json', $composer_json_content ) ) {
WP_CLI::error( "Error creating file: {$package_dir}/composer.json" );
}
}

if ( 'none' === strtolower( $license_input ) ) {
if ( is_file( $package_dir . '/LICENSE' ) ) {
unlink( $package_dir . '/LICENSE' );
Comment thread
ara303 marked this conversation as resolved.
}
} else {
$license_file_path = $this->resolve_license_file_path( $license_input, $template_path );
if ( null !== $license_file_path ) {
$license_data = [
'year' => gmdate( 'Y' ),
'name' => $composer_obj['name'],
];
$this->create_files(
[ "{$package_dir}/LICENSE" => Utils\mustache_render( $license_file_path, $license_data ) ],
$force
);
}
}
}

/**
Expand Down Expand Up @@ -835,6 +928,18 @@ public function package_tests( $args, $assoc_args ) {
}
}

private function resolve_license_file_path( $license, $template_path ) {
$normalized = strtolower( $license );
if ( basename( $normalized ) !== $normalized ) {
return null;
}
$license_path = $template_path . 'licenses/' . $normalized;
if ( is_file( $license_path ) ) {
return $license_path;
}
return null;
}
Comment thread
ara303 marked this conversation as resolved.

private static function rewrap_param_desc( $matches ) {
$param = $matches[1];
$desc = self::indent( "\t\t", self::normalize_desc_indentation( rtrim( $matches[2] ) ) );
Expand Down
14 changes: 14 additions & 0 deletions templates/licenses/0bsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
BSD Zero Clause License

Copyright (c) {{year}} {{name}}

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Loading
Loading