From 7adcf7b8110510cfc61ef1b354af5f097924df53 Mon Sep 17 00:00:00 2001 From: KIKOmanasijev Date: Sun, 26 May 2024 17:06:06 +0200 Subject: [PATCH 1/4] Feat: Add script to replace keyword placeholders with user input Fix: config file name not changing Opt: remove unused variables Fix: author_email not changing in composer.json Fix: composer package name placeholder use correct variable Fix: don't run composer test script because it does not exist --- composer.json | 54 +++++------ configure.php | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+), 27 deletions(-) create mode 100644 configure.php diff --git a/composer.json b/composer.json index 0b27b70..b354106 100644 --- a/composer.json +++ b/composer.json @@ -1,30 +1,30 @@ { - "name": "vendor-name/example-package", - "type": "package", - "description": "An example package for Roots Acorn.", - "license": "MIT", - "authors": [ - { - "name": "Brandon Nifong", - "email": "brandon@tendency.me" + "name": ":vendor_slug/:package_slug", + "type": "package", + "description": ":package_description", + "license": "MIT", + "authors": [ + { + "name": ":author_name", + "email": ":author_email" + } + ], + "autoload": { + "psr-4": { + "VendorName\\ExamplePackage\\": "src/" + } + }, + "require": { + "php": "^8.0" + }, + "extra": { + "acorn": { + "providers": [ + "VendorName\\ExamplePackage\\Providers\\ExampleServiceProvider" + ], + "aliases": { + "Example": "VendorName\\ExamplePackage\\Facades\\Example" + } + } } - ], - "autoload": { - "psr-4": { - "VendorName\\ExamplePackage\\": "src/" - } - }, - "require": { - "php": "^8.0" - }, - "extra": { - "acorn": { - "providers": [ - "VendorName\\ExamplePackage\\Providers\\ExampleServiceProvider" - ], - "aliases": { - "Example": "VendorName\\ExamplePackage\\Facades\\Example" - } - } - } } diff --git a/configure.php b/configure.php new file mode 100644 index 0000000..68395c0 --- /dev/null +++ b/configure.php @@ -0,0 +1,259 @@ +#!/usr/bin/env php + true, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTPGET => true, + CURLOPT_HTTPHEADER => [ + 'User-Agent: spatie-configure-script/1.0', + ], + ]); + + $response = curl_exec($curl); + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + curl_close($curl); + + if ($statusCode === 200) { + return json_decode($response); + } + } catch (Exception $e) { + // ignore + } + + return null; +} + +function searchCommitsForGitHubUsername(): string +{ + $authorName = strtolower(trim(shell_exec('git config user.name'))); + + $committersRaw = shell_exec("git log --author='@users.noreply.github.com' --pretty='%an:%ae' --reverse"); + $committersLines = explode("\n", $committersRaw ?? ''); + $committers = array_filter(array_map(function ($line) use ($authorName) { + $line = trim($line); + [$name, $email] = explode(':', $line) + [null, null]; + + return [ + 'name' => $name, + 'email' => $email, + 'isMatch' => strtolower($name) === $authorName && ! str_contains($name, '[bot]'), + ]; + }, $committersLines), fn ($item) => $item['isMatch']); + + if (empty($committers)) { + return ''; + } + + $firstCommitter = reset($committers); + + return explode('@', $firstCommitter['email'])[0] ?? ''; +} + +function guessGitHubUsernameUsingCli() +{ + try { + if (preg_match('/ogged in to github\.com as ([a-zA-Z-_]+).+/', shell_exec('gh auth status -h github.com 2>&1'), $matches)) { + return $matches[1]; + } + } catch (Exception $e) { + // ignore + } + + return ''; +} + +function guessGitHubUsername(): string +{ + $username = searchCommitsForGitHubUsername(); + if (! empty($username)) { + return $username; + } + + $username = guessGitHubUsernameUsingCli(); + if (! empty($username)) { + return $username; + } + + // fall back to using the username from the git remote + $remoteUrl = shell_exec('git config remote.origin.url'); + $remoteUrlParts = explode('/', str_replace(':', '/', trim($remoteUrl))); + + return $remoteUrlParts[1] ?? ''; +} + +function guessGitHubVendorInfo($authorName, $username): array +{ + $remoteUrl = shell_exec('git config remote.origin.url'); + $remoteUrlParts = explode('/', str_replace(':', '/', trim($remoteUrl))); + + $response = getGitHubApiEndpoint("orgs/{$remoteUrlParts[1]}"); + + if ($response === null) { + return [$authorName, $username]; + } + + return [$response->name ?? $authorName, $response->login ?? $username]; +} + +$gitName = run('git config user.name'); +$authorName = ask('Author name', $gitName); + +$gitEmail = run('git config user.email'); +$authorEmail = ask('Author email', $gitEmail); +$authorUsername = ask('Author username', guessGitHubUsername()); + +$guessGitHubVendorInfo = guessGitHubVendorInfo($authorName, $authorUsername); + +$vendorName = ask('Vendor name', $guessGitHubVendorInfo[0]); +$vendorUsername = ask('Vendor username', $guessGitHubVendorInfo[1] ?? slugify($vendorName)); +$vendorSlug = slugify($vendorUsername); + +$vendorNamespace = str_replace(' ', '', str_replace('-', '', ucwords($vendorName))); +$vendorNamespace = ask('Vendor namespace', $vendorNamespace); + +$currentDirectory = getcwd(); +$folderName = basename($currentDirectory); + +$packageName = ask('Package name', $folderName); +$packageSlug = slugify($packageName); + +$className = title_case($packageName); +$className = ask('Class name', $className); +$variableName = lcfirst($className); +$description = ask('Package description', "This is my package {$packageSlug}"); + +writeln('------'); +writeln("Author : {$authorName} ({$authorUsername}, {$authorEmail})"); +writeln("Vendor : {$vendorName} ({$vendorSlug})"); +writeln("Package : {$packageSlug} <{$description}>"); +writeln("Namespace : {$vendorNamespace}\\{$className}"); +writeln("Class name : {$className}"); +writeln('------'); + +writeln('This script will replace the above values in all relevant files in the project directory.'); + +if (! confirm('Modify files?', true)) { + exit(1); +} + +$files = (str_starts_with(strtoupper(PHP_OS), 'WIN') ? replaceForWindows() : replaceForAllOtherOSes()); + +foreach ($files as $file) { + replace_in_file($file, [ + ':author_name' => $authorName, + ':author_username' => $authorUsername, + ':author_email' => $authorEmail, + ':vendor_name' => $vendorNamespace, + ':vendor_slug' => $vendorSlug, + 'VendorName' => $vendorNamespace, + ':package_name' => $packageName, + ':package_slug' => $packageSlug, + 'Example' => $className, + 'ExamplePackage' => $className, + 'example' => $packageSlug, + ':package_description' => $description, + ]); + + match (true) { + str_contains($file, determineSeparator('src/Example.php')) => rename($file, determineSeparator('./src/'.$className.'.php')), + str_contains($file, determineSeparator('src/Providers/ExampleServiceProvider.php')) => rename($file, determineSeparator('./src/providers/'.$className.'ServiceProvider.php')), + str_contains($file, determineSeparator('src/Console/ExampleCommand.php')) => rename($file, determineSeparator('./src/console/'.$className.'.php')), + str_contains($file, determineSeparator('src/Facades/Example.php')) => rename($file, determineSeparator('./src/Facades/'.$className.'.php')), + str_contains($file, determineSeparator('resources/views/example.blade.php')) => rename($file, determineSeparator('./resources/views/'.$packageSlug.'.blade.php')), + default => [], + }; +} + +rename(determineSeparator('config/example.php'), determineSeparator('./config/'.$packageSlug.'.php')); + +confirm('Execute `composer install`?') && run('composer install'); + +confirm('Let this script delete itself?', true) && unlink(__FILE__); From 411717964a684053e21b538d253489ae39b8b16d Mon Sep 17 00:00:00 2001 From: KIKOmanasijev Date: Sun, 26 May 2024 21:01:44 +0200 Subject: [PATCH 2/4] Opt: improve consistency in composer.json str replacements --- composer.json | 7 ++++--- configure.php | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b354106..e6d3a3e 100644 --- a/composer.json +++ b/composer.json @@ -11,19 +11,20 @@ ], "autoload": { "psr-4": { - "VendorName\\ExamplePackage\\": "src/" + ":vendor_name\\:class_name\\": "src/" } }, "require": { + "php": "^8.0" }, "extra": { "acorn": { "providers": [ - "VendorName\\ExamplePackage\\Providers\\ExampleServiceProvider" + ":vendor_name\\:class_name\\Providers\\:class_nameServiceProvider" ], "aliases": { - "Example": "VendorName\\ExamplePackage\\Facades\\Example" + ":class_name": ":vendor_name\\:class_name\\Facades\\:class_name" } } } diff --git a/configure.php b/configure.php index 68395c0..b751dfe 100644 --- a/configure.php +++ b/configure.php @@ -75,12 +75,12 @@ function determineSeparator(string $path): string function replaceForWindows(): array { - return preg_split('/\\r\\n|\\r|\\n/', run('dir /S /B * | findstr /v /i .git\ | findstr /v /i vendor | findstr /v /i '.basename(__FILE__).' | findstr /r /i /M /F:/ ":author :vendor :package VendorName skeleton migration_table_name vendor_name vendor_slug author@domain.com"')); + return preg_split('/\\r\\n|\\r|\\n/', run('dir /S /B * | findstr /v /i .git\ | findstr /v /i vendor | findstr /v /i '.basename(__FILE__).' | findstr /r /i /M /F:/ ":author :vendor :package VendorName vendor_name vendor_slug author@domain.com"')); } function replaceForAllOtherOSes(): array { - return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|skeleton|migration_table_name|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v '.basename(__FILE__))); + return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v '.basename(__FILE__))); } function getGitHubApiEndpoint(string $endpoint): ?stdClass @@ -240,6 +240,7 @@ function guessGitHubVendorInfo($authorName, $username): array 'ExamplePackage' => $className, 'example' => $packageSlug, ':package_description' => $description, + ':class_name' => $className ]); match (true) { From 3a5fcefc432784c73029c8f1691f8eee042390b9 Mon Sep 17 00:00:00 2001 From: KIKOmanasijev Date: Mon, 27 May 2024 09:12:00 +0200 Subject: [PATCH 3/4] Opt: improve code styling in composer.json --- composer.json | 55 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/composer.json b/composer.json index e6d3a3e..6d2aa42 100644 --- a/composer.json +++ b/composer.json @@ -1,31 +1,30 @@ { - "name": ":vendor_slug/:package_slug", - "type": "package", - "description": ":package_description", - "license": "MIT", - "authors": [ - { - "name": ":author_name", - "email": ":author_email" - } - ], - "autoload": { - "psr-4": { - ":vendor_name\\:class_name\\": "src/" - } - }, - "require": { - - "php": "^8.0" - }, - "extra": { - "acorn": { - "providers": [ - ":vendor_name\\:class_name\\Providers\\:class_nameServiceProvider" - ], - "aliases": { - ":class_name": ":vendor_name\\:class_name\\Facades\\:class_name" - } - } + "name": ":vendor_slug/:package_slug", + "type": "package", + "description": ":package_description", + "license": "MIT", + "authors": [ + { + "name": ":author_name", + "email": ":author_email" } + ], + "autoload": { + "psr-4": { + ":vendor_name\\:class_name\\": "src/" + } + }, + "require": { + "php": "^8.1" + }, + "extra": { + "acorn": { + "providers": [ + ":vendor_name\\:class_name\\Providers\\:class_nameServiceProvider" + ], + "aliases": { + ":class_name": ":vendor_name\\:class_name\\Facades\\:class_name" + } + } + } } From 3003fc729bcd2e19ec3ee950cf2b4822a0f65091 Mon Sep 17 00:00:00 2001 From: KIKOmanasijev Date: Mon, 27 May 2024 09:26:19 +0200 Subject: [PATCH 4/4] Opt: simplify configure.php --- configure.php | 108 ++------------------------------------------------ 1 file changed, 3 insertions(+), 105 deletions(-) diff --git a/configure.php b/configure.php index b751dfe..9133ad5 100644 --- a/configure.php +++ b/configure.php @@ -83,117 +83,15 @@ function replaceForAllOtherOSes(): array return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v '.basename(__FILE__))); } -function getGitHubApiEndpoint(string $endpoint): ?stdClass -{ - try { - $curl = curl_init("https://api.github.com/{$endpoint}"); - curl_setopt_array($curl, [ - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_HTTPGET => true, - CURLOPT_HTTPHEADER => [ - 'User-Agent: spatie-configure-script/1.0', - ], - ]); - - $response = curl_exec($curl); - $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); - - curl_close($curl); - - if ($statusCode === 200) { - return json_decode($response); - } - } catch (Exception $e) { - // ignore - } - - return null; -} - -function searchCommitsForGitHubUsername(): string -{ - $authorName = strtolower(trim(shell_exec('git config user.name'))); - - $committersRaw = shell_exec("git log --author='@users.noreply.github.com' --pretty='%an:%ae' --reverse"); - $committersLines = explode("\n", $committersRaw ?? ''); - $committers = array_filter(array_map(function ($line) use ($authorName) { - $line = trim($line); - [$name, $email] = explode(':', $line) + [null, null]; - - return [ - 'name' => $name, - 'email' => $email, - 'isMatch' => strtolower($name) === $authorName && ! str_contains($name, '[bot]'), - ]; - }, $committersLines), fn ($item) => $item['isMatch']); - - if (empty($committers)) { - return ''; - } - - $firstCommitter = reset($committers); - - return explode('@', $firstCommitter['email'])[0] ?? ''; -} - -function guessGitHubUsernameUsingCli() -{ - try { - if (preg_match('/ogged in to github\.com as ([a-zA-Z-_]+).+/', shell_exec('gh auth status -h github.com 2>&1'), $matches)) { - return $matches[1]; - } - } catch (Exception $e) { - // ignore - } - - return ''; -} - -function guessGitHubUsername(): string -{ - $username = searchCommitsForGitHubUsername(); - if (! empty($username)) { - return $username; - } - - $username = guessGitHubUsernameUsingCli(); - if (! empty($username)) { - return $username; - } - - // fall back to using the username from the git remote - $remoteUrl = shell_exec('git config remote.origin.url'); - $remoteUrlParts = explode('/', str_replace(':', '/', trim($remoteUrl))); - - return $remoteUrlParts[1] ?? ''; -} - -function guessGitHubVendorInfo($authorName, $username): array -{ - $remoteUrl = shell_exec('git config remote.origin.url'); - $remoteUrlParts = explode('/', str_replace(':', '/', trim($remoteUrl))); - - $response = getGitHubApiEndpoint("orgs/{$remoteUrlParts[1]}"); - - if ($response === null) { - return [$authorName, $username]; - } - - return [$response->name ?? $authorName, $response->login ?? $username]; -} - $gitName = run('git config user.name'); $authorName = ask('Author name', $gitName); $gitEmail = run('git config user.email'); $authorEmail = ask('Author email', $gitEmail); -$authorUsername = ask('Author username', guessGitHubUsername()); - -$guessGitHubVendorInfo = guessGitHubVendorInfo($authorName, $authorUsername); +$authorUsername = ask('Author username', 'developer@roots.io'); -$vendorName = ask('Vendor name', $guessGitHubVendorInfo[0]); -$vendorUsername = ask('Vendor username', $guessGitHubVendorInfo[1] ?? slugify($vendorName)); +$vendorName = ask('Vendor name', 'Roots'); +$vendorUsername = ask('Vendor username', 'roots'); $vendorSlug = slugify($vendorUsername); $vendorNamespace = str_replace(' ', '', str_replace('-', '', ucwords($vendorName)));