diff --git a/bin/git-close-pull-request b/bin/git-close-pull-request deleted file mode 100755 index 67f3673d..00000000 --- a/bin/git-close-pull-request +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env php -<?php - -declare(strict_types=1); - -/** - * Usage: git close-pull-request -t <target> - * - * Run this from a branch which has an upstream remote branch, and an associated - * pull request. - * - * The script will merge the branch into master, push master (which will - * automatically close the pull request), and delete both the local and remote - * branches. - * - * Based on a script by @christoomey. Translated into PHP. - */ - -class ClosesPullRequests -{ - private $targetBranch; - private $localBranch; - private $remoteBranch; - - private const RUN_TYPE_COMMAND = 'command'; - private const RUN_TYPE_QUERY = 'query'; - - public function __construct() - { - $this->localBranch = $this->run( - 'git rev-parse --abbrev-ref HEAD', - self::RUN_TYPE_QUERY - ); - $this->targetBranch = $this->getTargetBranchFromArgs(); - - $this->remoteBranch = $this->run( - 'git rev-parse --abbrev-ref --symbolic-full-name @{u}', - self::RUN_TYPE_QUERY - ); - $this->remoteBranch = str_replace('origin/', '', $this->remoteBranch); - } - - public function __invoke(): void - { - $this->confirmCiStatusIsPassing(); - // TODO: Check that the current branch has a tracking branch. - $this->ensureWorkingDirectoryAndIndexAreClean(); - $this->fetchOrigin(); - $this->ensureFeatureBranchInSync(); - $this->ensureTargetBranchInSync(); - $this->checkoutTargetBranch(); - $this->mergeLocalBranch(); - $this->pushTargetBranch(); - $this->deleteRemoteBranch(); - $this->deleteLocalBranch(); - } - - private function ensureWorkingDirectoryAndIndexAreClean(): void - { - echo 'Ensuring that index and working directory are clean...' . PHP_EOL; - - $isIndexClean = $this->run('git diff --cached --exit-code', self::RUN_TYPE_COMMAND); - $isWorkingDirClean = $this->run('git diff --exit-code', self::RUN_TYPE_COMMAND); - - if (!$isIndexClean || !$isWorkingDirClean) { - $this->dieWithMessage('Index or working dir not clean. Aborting.'); - } - } - - private function getTargetBranchFromArgs(): string - { - if (!$targetBranchName = $this->getArg('t:', ['target:'])) { - $this->dieWithMessage('Invalid target branch specified. Aborting.'); - } - - return $targetBranchName; - } - - private function confirmCiStatusIsPassing(): void - { - if ($this->isForce()) { - echo 'Forced. Skipping ci-status check...' . PHP_EOL; - return; - } - - echo 'Confirming ci-status on PR is green...' . PHP_EOL; - - $passedCi = $this->run('gh pr checks', self::RUN_TYPE_COMMAND); - - // TODO: Check if there are no CI checks. Does this return `true` as well? - if (!$passedCi) { - $this->dieWithMessage('CI pending or failed.'); - } - } - - private function fetchOrigin(): void - { - print 'Fetching origin to confirm local and remote in sync...' - . PHP_EOL; - - $this->run('git fetch origin', self::RUN_TYPE_COMMAND); - } - - private function ensureTargetBranchInSync(): void - { - $this->ensureBranchInSyncWithUpstream( - $this->targetBranch, - $this->targetBranch - ); - } - - private function ensureFeatureBranchInSync(): void - { - $this->ensureBranchInSyncWithUpstream( - $this->localBranch, - $this->remoteBranch - ); - } - - private function ensureBranchInSyncWithUpstream( - string $localBranch, - string $remoteBranch - ): void { - echo sprintf( - 'Ensuring that %s is in sync with its upstream...', - $localBranch - ) . PHP_EOL; - - $localCommitTip = $this->tipCommitOfBranch($localBranch); - $remoteCommitTip = $this->tipCommitOfBranch(sprintf( - 'origin/%s', - $remoteBranch - )); - - if ($localCommitTip != $remoteCommitTip) { - $this->dieWithMessage(sprintf( - 'Branch %s was out of date, needs rebasing. Aborting.', - $localBranch - )); - } - } - - private function tipCommitOfBranch(string $branchName): string - { - return $this->run( - sprintf('git rev-parse %s', $branchName), - self::RUN_TYPE_QUERY - ); - } - - private function checkoutTargetBranch(): void - { - echo sprintf('Checking out %s...' . PHP_EOL, $this->targetBranch); - - $this->run( - sprintf('git checkout %s', $this->targetBranch), - self::RUN_TYPE_COMMAND - ); - } - - private function mergeLocalBranch(): void - { - echo sprintf( - 'Merging %s into %s...' . PHP_EOL, - $this->localBranch, - $this->targetBranch - ); - - $mergeCommand = sprintf('git merge --ff-only %s', $this->localBranch); - if (!$this->run($mergeCommand, self::RUN_TYPE_COMMAND)) { - // Switch back to the previous branch. - $this->run('git checkout -', self::RUN_TYPE_COMMAND); - - $this->dieWithMessage(sprintf( - 'Branch %s is not fast-forwardable.', - $this->localBranch - )); - } - } - - public function pushTargetBranch(): void - { - print(sprintf('Pushing updated %s branch...', $this->targetBranch)); - - $this->run( - sprintf('git push origin %s', $this->targetBranch), - self::RUN_TYPE_COMMAND - ); - } - - public function deleteRemoteBranch(): void - { - echo 'Deleting remote branch...' . PHP_EOL; - - $this->run( - sprintf('git push origin :%s', $this->remoteBranch), - self::RUN_TYPE_COMMAND - ); - } - - public function deleteLocalBranch(): void - { - echo 'Deleting local branch...' . PHP_EOL; - - $this->run( - sprintf('git branch -d %s', $this->localBranch), - self::RUN_TYPE_COMMAND - ); - } - - private function getArg(string $shortOpts, array $longOpts = []): ?string - { - if (!$values = getopt($shortOpts, $longOpts)) { - return NULL; - } - - return current($values); - } - - private function hasArg(string $shortOpts, array $longOpts = []): bool - { - return !empty(getopt($shortOpts, $longOpts)); - } - - private function isForce(): bool - { - return $this->hasArg('f::', ['force::']); - } - - /** - * Run the command. - * - * @return bool|string - * If the type is 'command', the method will return if there were any - * errors when running the command based on its return code. - * - * If the type is 'query', then the output of the command will be returned - * as a string. - */ - private function run(string $command, string $type) - { - switch ($type) { - case self::RUN_TYPE_COMMAND: - // Perform the command, hiding the original output and return - // whether or not there were errors. - @exec("$command", $output, $return); - - return $return == 0; - - case self::RUN_TYPE_QUERY: - // Perform the command and return the output. - return exec($command, $output); - } - } - - private function dieWithMessage(string $message): void - { - echo sprintf("\e[31m%s\e[0m", $message); - - exit(1); - } - - private function exitWithWarning(string $message): void - { - echo sprintf("\e[33m%s\e[0m", $message); - - exit(2); - } -} - -(new ClosesPullRequests())->__invoke(); diff --git a/bin/git-create-new-tracking-branch b/bin/git-create-new-tracking-branch deleted file mode 100755 index 0a14fb4b..00000000 --- a/bin/git-create-new-tracking-branch +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -e - -if [ "$#" -lt 1 ]; then - echo "Error: Not enough arguments." - exit l -fi - -# Create a new branch including any additional arguments. -git checkout -b "$@" - -# Push the branch to origin, bypassing any Git hooks. -new_branch_name=$1 -git push --no-verify -u origin "${new_branch_name}:opd-${new_branch_name}" diff --git a/bin/git-delete-merged-branches b/bin/git-delete-merged-branches deleted file mode 100755 index 77e7fc00..00000000 --- a/bin/git-delete-merged-branches +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env php -<?php - -function extractBranchNamesFromInfo(string $branchInfo): array -{ - $branchNames = array_map(function (string $branchInfo): string { - preg_match('/\s*((\w|-|\/)+)\s*/', $branchInfo, $matches); - - return $matches[1] ?? ''; - }, explode(PHP_EOL, $branchInfo)); - - return array_filter($branchNames); -} - -function filterIgnoredBranches(array $branchNames): array -{ - return array_filter($branchNames, function (string $branchName): bool { - return !in_array($branchName, ['develop', 'master', 'staging', 'production']); - }); -} - -$branchInfo = shell_exec('git branch -vv | grep ": gone]"'); - -# Return early if there are no branches to delete. -if ($branchInfo === NULL) { - return; -} - -$branchNames = extractBranchNamesFromInfo($branchInfo); -$filteredBranchNames = filterIgnoredBranches($branchNames); - -$currentBranch = exec('git rev-parse --abbrev-ref HEAD'); - -foreach ($filteredBranchNames as $branchName) { - if ($branchName == $currentBranch) { - echo "Cannot delete {$branchName} as it is the current branch."; - continue; - } - - echo "Deleting {$branchName}..."; - exec("git branch -D ${branchName}"); -} diff --git a/bin/git-master-to-main-wrapper b/bin/git-master-to-main-wrapper deleted file mode 100755 index bfef84b5..00000000 --- a/bin/git-master-to-main-wrapper +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env zsh - -# Usage: instead of -# -# git rebase -i master -# -# run this: -# -# git master-to-main-wrapper rebase -i %BRANCH% -# -# It will replace the literal string `%BRANCH%` with "main" (preferred) or -# "master" depending on what the current repository uses. - -command=$* -branchname=$(main-or-master-branch) -replaced_commands=$(echo $command | sed "s/%BRANCH%/$branchname/g") -# sh_glob ignores special meaning of parentheses so that fancy logs like this -# work: `git master-to-main-wrapper log --format='%w(78)%s%n%+b'` -zsh -c "setopt sh_glob; git ${replaced_commands}" \ No newline at end of file diff --git a/bin/git-opr b/bin/git-opr deleted file mode 100755 index 642f5f56..00000000 --- a/bin/git-opr +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -set -e - -ensure_is_published() { - [[ ! $is_published ]] && git publish -} - -is_published() { - echo $(git upstream) -} - -open_or_build_pull_request() { - type gh &>/dev/null - - if [ $? -ne 0 ]; then - echo "Error: gh command not found." - exit 1 - fi - - # Load an existing PR, or create a new one. - gh pr view --web || gh pr create --assignee opdavies --web -} - -ensure_is_published -open_or_build_pull_request diff --git a/bin/git-publish b/bin/git-publish deleted file mode 100755 index ca196bf7..00000000 --- a/bin/git-publish +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env php -<?php - -/** - * Usage: git publish - */ - -$currentBranch = exec('git rev-parse --abbrev-ref HEAD'); - -if (in_array($currentBranch, ['develop', 'main', 'master', 'staging', 'production'])) { - print "Currently on ${currentBranch}. Aborting."; - exit(1); -} - -exec("git push -u origin $currentBranch:opd-{$currentBranch}"); diff --git a/bin/git.sh b/bin/git.sh deleted file mode 100755 index 9be64daa..00000000 --- a/bin/git.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# The MIT License (MIT) -# Copyright (c) 2013 Alvin Abad - -if [ $# -eq 0 ]; then - echo "Git wrapper script that can specify an ssh-key file -Usage: - git.sh -i ssh-key-file git-command - " - exit 1 -fi - -# remove temporary file on exit -trap 'rm -f /tmp/.git_ssh.$$' 0 - -if [ "$1" = "-i" ]; then - SSH_KEY=$2; shift; shift - echo "ssh -i $SSH_KEY \$@" > /tmp/.git_ssh.$$ - chmod +x /tmp/.git_ssh.$$ - export GIT_SSH=/tmp/.git_ssh.$$ -fi - -# in case the git command is repeated -[ "$1" = "git" ] && shift - -# Run the git command -git "$@" diff --git a/bin/phpunit-or-pest b/bin/phpunit-or-pest deleted file mode 100755 index 781b7124..00000000 --- a/bin/phpunit-or-pest +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ -f "vendor/bin/pest" ]]; then - echo "pest" - exit 0 -fi - -echo "phpunit" diff --git a/bin/tmuxinator-fzf b/bin/tmuxinator-fzf deleted file mode 100755 index 595a9fa2..00000000 --- a/bin/tmuxinator-fzf +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -# Use fzf to select a project to open with tmuxinator. - -set -euo pipefail - -tmuxinator list -n | tail -n +2 | fzf | xargs tmuxinator start diff --git a/bin/watch-changes b/bin/watch-changes deleted file mode 100755 index 2978e290..00000000 --- a/bin/watch-changes +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -if [ "$1" ] && [ "$2" ]; then - while true - do - inotifywait --event modify --exclude ".null-ls_*" --recursive $1 2> /dev/null - $2 - done -else - echo "usage: watch-changes <file> <command>" -fi