From 4e8489dd128b0970acbf1d30922b46ec629edeb3 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 21 Apr 2018 13:00:56 +0100 Subject: [PATCH 01/65] Remove initial `read -r path` in dependency_file_exists() to stop excluding first match --- asimov | 2 -- 1 file changed, 2 deletions(-) diff --git a/asimov b/asimov index fc01dd4..6b048d7 100755 --- a/asimov +++ b/asimov @@ -30,8 +30,6 @@ readonly FILEPATHS=( dependency_file_exists() { filename=$1 - read -r path; - while read -r path; do # Return early if this is a nested dependency (e.g. node_modules From 16f40d6b45235ea97ebba27580641b373179a359 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 21 Apr 2018 13:01:31 +0100 Subject: [PATCH 02/65] Output directory size the first time a directory is excluded for maximum satisfaction --- asimov | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asimov b/asimov index fc01dd4..cb96e88 100755 --- a/asimov +++ b/asimov @@ -56,7 +56,8 @@ exclude_file() { tmutil addexclusion "$path" - echo "- ${path} has been excluded from Time Machine backups." + sizeondisk=$(du -hs "$path" | cut -f1) + echo "- ${path} has been excluded from Time Machine backups ($sizeondisk)." done } From c344bf2fc74332b5e2c8968783837dcce879a9fb Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 21 Apr 2018 14:20:50 +0100 Subject: [PATCH 03/65] Switch to using find's -prune switch to exclude match subdirectories for speed, and exclude ~/Library folder from searches --- asimov | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/asimov b/asimov index fc01dd4..62dbc1e 100755 --- a/asimov +++ b/asimov @@ -33,13 +33,6 @@ dependency_file_exists() { read -r path; while read -r path; do - - # Return early if this is a nested dependency (e.g. node_modules - # inside another node_modules directory. - if [[ $(dirname "$path") == *"/$(basename "$path")/"* ]]; then - continue; - fi - if [ -f "${path}/${filename}" ]; then echo "$path" fi @@ -67,5 +60,5 @@ for i in "${FILEPATHS[@]}"; do printf "\\n\\033[0;36mFinding %s/ directories with corresponding %s files...\\033[0m\\n" \ "${parts[0]}" "${parts[1]}" - find ~ -name "${parts[0]}" -type d | dependency_file_exists "${parts[1]}" | exclude_file + find ~ -not \( -path ~/Library -prune \) -name "${parts[0]}" -type d -prune | dependency_file_exists "${parts[1]}" | exclude_file done From 9648820ddc1b26f7a93cb05f0375958f91efa677 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 21 Apr 2018 18:56:03 +0100 Subject: [PATCH 04/65] Rework the `find` command and path variables so that `find` is only run once however many FILEPATHS are set --- asimov | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/asimov b/asimov index 62dbc1e..10d7fa4 100755 --- a/asimov +++ b/asimov @@ -28,15 +28,15 @@ readonly FILEPATHS=( # For example, when looking at a /vendor directory, we may choose to # ensure a composer.json file is available. dependency_file_exists() { - filename=$1 - read -r path; while read -r path; do - if [ -f "${path}/${filename}" ]; then + safe_filepath_suffix=$(md5 -qs $(basename "$path")) + filename="filepath_${safe_filepath_suffix}" + if [ -f "${path}/${!filename}" ]; then echo "$path" fi - done + done } # Exclude the given path from Time Machine backups. @@ -53,12 +53,30 @@ exclude_file() { done } +# Start to construct the `find` parameter arguments, based on a home directory search +# but excluding ~/Library +find_parameters=(~ -not \( -path ~/Library -prune \)) + # Iterate over dependencies. +n=0 for i in "${FILEPATHS[@]}"; do read -ra parts <<< "$i" - printf "\\n\\033[0;36mFinding %s/ directories with corresponding %s files...\\033[0m\\n" \ - "${parts[0]}" "${parts[1]}" + # Add this folder to the `find` list, allowing a single `find` command to find all + if [ "$n" -gt "0" ]; then + find_parameters+=(-o) + fi + find_parameters+=(-name "${parts[0]}" -type d -prune) + + # Set up a variable for lookup in dependency_file_exists, using a hashed name + # to ensure the variable name is valid + safe_filepath_suffix=$(md5 -qs "${parts[0]}") + declare "filepath_${safe_filepath_suffix}"="${parts[1]}" - find ~ -not \( -path ~/Library -prune \) -name "${parts[0]}" -type d -prune | dependency_file_exists "${parts[1]}" | exclude_file + ((n++)) done + + +echo -e "\\n\\033[0;36mFinding dependency directories with corresponding definition files...\\033[0m\\n" + +find "${find_parameters[@]}" | dependency_file_exists | exclude_file From 3d88b6732be7e0b75637b79c3c273fb511fc3995 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Wed, 13 Jun 2018 21:53:10 -0400 Subject: [PATCH 05/65] Add a .travis.yml file for Travis CI integration (shellcheck) --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5f14786 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: bash + +notifications: + email: never + +sudo: false + +script: + - shellcheck asimov *.sh + +matrix: + fast_finish: true From 2908c3eedaba5f4adb633660b8fa14276571f0e2 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Wed, 13 Jun 2018 21:59:20 -0400 Subject: [PATCH 06/65] Quote the result of `$(basename "$path")` to prevent string splitting, at the recommendation of shellcheck --- asimov | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asimov b/asimov index 8243ee2..ee09ca3 100755 --- a/asimov +++ b/asimov @@ -31,7 +31,7 @@ dependency_file_exists() { read -r path; while read -r path; do - safe_filepath_suffix=$(md5 -qs $(basename "$path")) + safe_filepath_suffix=$(md5 -qs "$(basename "$path")") filename="filepath_${safe_filepath_suffix}" if [ -f "${path}/${!filename}" ]; then echo "$path" From fd3388e742feb6a06eb9f62a1f06b7ba22db4fea Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Wed, 13 Jun 2018 22:00:15 -0400 Subject: [PATCH 07/65] Shellcheck wasn't crazy about concatenating a string within a `declare` statement, so set the full variable value on the line above, instead --- asimov | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asimov b/asimov index ee09ca3..8af260e 100755 --- a/asimov +++ b/asimov @@ -71,8 +71,8 @@ for i in "${FILEPATHS[@]}"; do # Set up a variable for lookup in dependency_file_exists, using a hashed name # to ensure the variable name is valid - safe_filepath_suffix=$(md5 -qs "${parts[0]}") - declare "filepath_${safe_filepath_suffix}"="${parts[1]}" + safe_filepath="filepath_$(md5 -qs "${parts[0]}")" + declare "$safe_filepath"="${parts[1]}" ((n++)) done From 225bb5bae08616eaf43a95c4429d5798625ab6e6 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Wed, 13 Jun 2018 22:02:10 -0400 Subject: [PATCH 08/65] Add the Travis CI build status to the README file --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed3fdb2..96fe14c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Asimov +[![Build Status](https://travis-ci.com/stevegrunwell/asimov.svg?branch=master)](https://travis-ci.com/stevegrunwell/asimov) + > Those people who think they know everything are a great annoyance to those of us who do.
— Issac Asimov For macOS users, [Time Machine](https://support.apple.com/en-us/HT201250) is a no-frills, set-it-and-forget-it solution for on-site backups. Plug in an external hard drive (or configure a network storage drive), and your Mac's files are backed up. @@ -41,4 +43,4 @@ If a directory has been excluded from backups in error, you can remove the exclu ```bash $ tmutil removeexclusion /path/to/directory -``` \ No newline at end of file +``` From dce102e98c141cc221fa8dae55d57ea55099e3c6 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Wed, 13 Jun 2018 22:07:41 -0400 Subject: [PATCH 09/65] Include an .editorconfig file in the project This file ensures that IDEs that support [the .editorconfig standard](https://editorconfig.org/) will automatically handle appropriate coding standards. --- .editorconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..08b4f22 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.yml] +indent_style = space +indent_size = 2 From 7d9cd818abd610526d2666b095d76a1d5c2e47d0 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 23 Jun 2018 00:32:32 +0200 Subject: [PATCH 10/65] Exclude bower_components directory --- asimov | 1 + 1 file changed, 1 insertion(+) diff --git a/asimov b/asimov index 8af260e..2531137 100755 --- a/asimov +++ b/asimov @@ -20,6 +20,7 @@ readonly FILEPATHS=( "vendor ../composer.json" "node_modules ../package.json" ".vagrant ../Vagrantfile" + "bower_components ../bower.json" ) # Given a directory path, determine if the corresponding file (relative From ed833ff5e9eb90ffc6c4cb0200f4fffdd9d2a494 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sat, 1 Sep 2018 13:14:05 -0400 Subject: [PATCH 11/65] Add tests cases for the project using PHPUnit While PHPUnit isn't the perfect tool for testing shell scripts, it does give us the necessary tools to create a temporary filesystem with a pre-determined structure, as well as the ability to overwrite environment variables to scope Asimov to our dummy directory. In this particular case, we're overloading the tmutil application with a PHP test double, enabling us to track what's called without actually relying on tmutil. --- .editorconfig | 3 + .gitignore | 3 +- composer.json | 32 + composer.lock | 1426 ++++++++++++++++++++++++++++++++++++++++++ phpunit.xml.dist | 16 + tests/AsimovTest.php | 40 ++ tests/TMUtilMock.php | 41 ++ tests/TestCase.php | 174 ++++++ tests/bin/tmutil | 19 + 9 files changed, 1753 insertions(+), 1 deletion(-) create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 phpunit.xml.dist create mode 100644 tests/AsimovTest.php create mode 100644 tests/TMUtilMock.php create mode 100644 tests/TestCase.php create mode 100755 tests/bin/tmutil diff --git a/.editorconfig b/.editorconfig index 08b4f22..5d68a00 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,9 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +[*.php] +indent_size = 4 + [*.yml] indent_style = space indent_size = 2 diff --git a/.gitignore b/.gitignore index 496ee2c..85d346a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.DS_Store \ No newline at end of file +vendor +.DS_Store diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..38536d7 --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "stevegrunwell/asimov", + "description": "Automatically exclude development dependencies from Apple Time Machine backups", + "type": "project", + "authors": [ + { + "name": "Steve Grunwell", + "homepage": "https://stevegrunwell.com" + } + ], + "support": { + "source": "https://github.com/stevegrunwell/asimov", + "issues": "https://github.com/stevegrunwell/asimov/issues" + }, + "license": "MIT", + "require-dev": { + "phpunit/phpunit": "^7.3" + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "config": { + "preferred-install": "dist", + "sort-packages": true, + "optimize-autoloader": true, + "platform": { + "php": "7.2" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..2ac5532 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1426 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "24a76b63a6599632bb89a5ab94236f91", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2017-07-22T11:58:36+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2018-06-11T23:09:50+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-30T07:14:17+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2018-08-05T17:53:17+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/865662550c384bc1db7e51d29aeda1c2c161d69a", + "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2018-06-01T07:51:50+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c", + "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2018-06-11T11:44:00+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2018-02-01T13:07:23+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2018-02-01T13:16:43+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.3.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", + "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.0", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2018-09-01T15:49:55+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "366541b989927187c4ca70490a35615d3fef2dce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", + "reference": "366541b989927187c4ca70490a35615d3fef2dce", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2018-06-10T07:54:39+00:00" + }, + { + "name": "sebastian/environment", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2017-07-01T08:51:00+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2017-04-03T13:19:02+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-01-29T19:49:41+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "platform-overrides": { + "php": "7.2" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..1ef4153 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,16 @@ + + + + + ./tests + + + diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php new file mode 100644 index 0000000..201dc20 --- /dev/null +++ b/tests/AsimovTest.php @@ -0,0 +1,40 @@ +createDirectoryStructure([ + 'Code' => [ + "My-$system-Project" => [ + $dependencies => [], + $config => 'Configuration for this platform.', + ], + ], + ]); + + $this->assertEquals( + [$this->getFilepath("Code/My-$system-Project/$dependencies")], + $this->asimov(), + "When a $config file is present, $dependencies/ should be excluded." + ); + } +} diff --git a/tests/TMUtilMock.php b/tests/TMUtilMock.php new file mode 100644 index 0000000..4d61d7f --- /dev/null +++ b/tests/TMUtilMock.php @@ -0,0 +1,41 @@ +stream = fopen('php://fd/' . self::DESCRIPTOR, 'a'); + } + + public function __destruct() + { + fclose($this->stream); + } + + public function addexclusion(string $path) + { + fwrite($this->stream, $path . PHP_EOL); + } + + public function isexcluded(string $path): bool + { + return false; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..21f9a58 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,174 @@ +isDir()) { + rmdir($file->getRealPath()); + } else { + unlink($file->getRealPath()); + } + } + } + + /** + * Destroy the temp directory at the conclusion of the test suite. + * + * @afterClass + */ + public static function removeTempDir() + { + rmdir(self::$homeDir); + } + + /** + * Execute the local copy of Asimov. + * + * @return array An array of excluded filepaths. + */ + protected function asimov(): array + { + $descriptors = [ + 1 => ['pipe', 'w'], + TMUtilMock::DESCRIPTOR => ['pipe', 'w'], + ]; + $env = [ + 'HOME' => self::$homeDir, + 'PATH' => __DIR__ . '/bin:' . getenv('PATH'), + ]; + $process = proc_open(dirname(__DIR__) . '/asimov', $descriptors, $pipes, null, $env); + + if (! is_resource($process)) { + trigger_error('Unable to call Asimov via proc_open().', E_USER_ERROR); + } + + $excluded = stream_get_contents($pipes[TMUtilMock::DESCRIPTOR]); + + proc_close($process); + + return array_filter(explode(PHP_EOL, $excluded)); + } + + /** + * Retrieve the full system path, relative to the temporary home directory. + * + * @param string $path Optional. The path to include. + * + * @return string The full system path to the given path within the home directory. + */ + protected function getFilepath(string $path = ''): string + { + $base = self::$homeDir; + + if ('/' !== substr($base, -1, 1)) { + $base .= '/'; + } + + if ('/' === substr($path, 0, 1)) { + $path = substr($path, 1); + } + + return $base . $path; + } + + /** + * Create dummy files within our dummy filesystem. + * + * A multi-dimensional array will be treated as a series of nested directories, using keys + * as directory names; non-array values will be written as file contents. + * + * For example, consider the following $structure array: + * + * [ + * 'parent-dir' => [ + * 'child-dir' => [ + * 'file.txt' => 'These are the contents of parent-dir/child-dir/file.txt', + * ], + * 'readme.txt' => 'This is the README file.', + * ], + * ] + * + * That array would produce a directory structure (within self::$homeDir) that looks like: + * + * - parent-dir/ + * |- child-dir/ + * |- file.txt + * |- readme.txt + * + * @param array $structure + */ + protected function createDirectoryStructure(array $structure) + { + @mkdir(self::$homeDir, 0777, true); + + foreach ($structure as $name => $data) { + $this->populateFilesystem($name, $data); + } + } + + /** + * Create a new directory in the dummy filesystem. + * + * This function is written to be called recursively, in order to populate nested arrays. + * + * @param string $name The directory or filename to create. + * @param mixed $data The data to associate with the name; arrays will be treated as + * sub-directories, while everything else will be written to files. + */ + private function populateFilesystem(string $name, $data) + { + if (is_array($data)) { + @mkdir(self::$homeDir . DIRECTORY_SEPARATOR . $name, 0777, true); + + foreach ($data as $subdir => $subdata) { + $this->populateFilesystem($name . DIRECTORY_SEPARATOR . $subdir, $subdata); + } + } else { + file_put_contents(self::$homeDir . DIRECTORY_SEPARATOR . $name, $data); + } + } +} diff --git a/tests/bin/tmutil b/tests/bin/tmutil new file mode 100755 index 0000000..b542b36 --- /dev/null +++ b/tests/bin/tmutil @@ -0,0 +1,19 @@ +#!/usr/bin/env php + $argc) { + throw new \ArgumentCountError('Expected to see "tmutil", the sub-command, and the path.'); +} + +$tmutil = new TMUtilMock; + +return call_user_func([$tmutil, $argv[1]], $argv[2]); From b69b8361c3493f59ee2295831abee9c3dcae09da Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sat, 1 Sep 2018 13:26:44 -0400 Subject: [PATCH 12/65] Add PHPUnit to the Travis CI configuration --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5f14786..b672c59 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,17 @@ -language: bash +language: php notifications: email: never sudo: false +php: 7.2 + +install: + - composer install --prefer-dist --no-suggest + script: + - phpunit - shellcheck asimov *.sh matrix: From 99355a8c8d0c9d9ebfdfad062f57693c12d4306c Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sat, 1 Sep 2018 14:17:56 -0400 Subject: [PATCH 13/65] Add a test to verify that multiple dependencies can be excluded in a single pass --- tests/AsimovTest.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 201dc20..3462979 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -37,4 +37,29 @@ public function testExcludesDependenciesWhenConfigFileIsPresent($system, $config "When a $config file is present, $dependencies/ should be excluded." ); } + + public function testCanExcludeMultipleDependencies() + { + $this->createDirectoryStructure([ + 'Code' => [ + 'First-Project' => [ + 'vendor' => [], + 'composer.json' => 'Configuration for this platform.', + ], + 'Second-Project' => [ + 'vendor' => [], + 'composer.json' => 'Configuration for this platform.', + ], + ], + ]); + + $this->assertEquals( + [ + $this->getFilepath('Code/First-Project/vendor'), + $this->getFilepath('Code/Second-Project/vendor'), + ], + $this->asimov(), + 'All matches should be excluded in a single pass.' + ); + } } From 3b12eccc17f4d18a319f8e61193f028d7e5fd4a8 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sat, 1 Sep 2018 15:06:11 -0400 Subject: [PATCH 14/65] Fix a regression that was originally fixed in #16 (unnecessary `read -r path`) --- asimov | 2 -- 1 file changed, 2 deletions(-) diff --git a/asimov b/asimov index 2531137..31707e5 100755 --- a/asimov +++ b/asimov @@ -29,8 +29,6 @@ readonly FILEPATHS=( # For example, when looking at a /vendor directory, we may choose to # ensure a composer.json file is available. dependency_file_exists() { - read -r path; - while read -r path; do safe_filepath_suffix=$(md5 -qs "$(basename "$path")") filename="filepath_${safe_filepath_suffix}" From 6914cbc1f727a9f3e13f719ad5255b3d2902a34c Mon Sep 17 00:00:00 2001 From: Norbert Schneider Date: Sat, 13 Oct 2018 12:30:53 +0200 Subject: [PATCH 15/65] Exclude Java Maven Build Folder This will exclude the Java Maven build folder "target". --- asimov | 1 + 1 file changed, 1 insertion(+) diff --git a/asimov b/asimov index 2531137..72c03a8 100755 --- a/asimov +++ b/asimov @@ -21,6 +21,7 @@ readonly FILEPATHS=( "node_modules ../package.json" ".vagrant ../Vagrantfile" "bower_components ../bower.json" + "target ../pom.xml" ) # Given a directory path, determine if the corresponding file (relative From b9a42065724fe956b40895b45fef5c3a6d56f2f6 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 12:58:22 -0400 Subject: [PATCH 16/65] Switch the test methods to use more descriptive names and the @test annotation --- tests/AsimovTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 3462979..e1cdb51 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -15,12 +15,13 @@ class AsimovTest extends TestCase * * When adding a simple pattern, please add it as a scenario for this test. * + * @test * @testWith ["Bower", "bower.json", "bower_components"] * ["Composer", "composer.json", "vendor"] * ["Node", "package.json", "node_modules"] * ["Vagrant", "Vagrantfile", ".vagrant"] */ - public function testExcludesDependenciesWhenConfigFileIsPresent($system, $config, $dependencies) + public function it_should_exclude_dependency_directories_when_a_config_file_is_present($system, $config, $dependencies) { $this->createDirectoryStructure([ 'Code' => [ @@ -38,7 +39,12 @@ public function testExcludesDependenciesWhenConfigFileIsPresent($system, $config ); } - public function testCanExcludeMultipleDependencies() + /** + * A run should pick up multiple dependencies, not just the first. + * + * @test + */ + public function it_should_find_multiple_matches() { $this->createDirectoryStructure([ 'Code' => [ From 47e4284b7374c753650f9b523a43d019ab128573 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 13:42:18 -0400 Subject: [PATCH 17/65] Enable Asimov to persist excluded paths between multiple runs within the same test method, then make sure that Asimov is checking to see if a path has been excluded before excluding it --- tests/AsimovTest.php | 27 +++++++++++++++++++++++++++ tests/TMUtilMock.php | 21 +++++++++++++++++++-- tests/TestCase.php | 31 +++++++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index e1cdb51..affa33c 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -68,4 +68,31 @@ public function it_should_find_multiple_matches() 'All matches should be excluded in a single pass.' ); } + + /** + * Once a dependency has been excluded, there's no need to exclude it again. + * + * @test + */ + public function it_should_only_exclude_new_matches() + { + $this->createDirectoryStructure([ + 'Code' => [ + 'My-Project' => [ + 'vendor' => [], + 'composer.json' => 'Configuration for this platform.', + ], + ], + ]); + + $this->assertNotEmpty( + $this->asimov(), + 'Asimov should have found one path on its first run.' + ); + + $this->assertEmpty( + $this->asimov(), + 'Asimov should not have found any new paths on the second run.' + ); + } } diff --git a/tests/TMUtilMock.php b/tests/TMUtilMock.php index 4d61d7f..a64a615 100644 --- a/tests/TMUtilMock.php +++ b/tests/TMUtilMock.php @@ -14,6 +14,11 @@ class TMUtilMock */ const DESCRIPTOR = 4; + /** + * @var array + */ + private $exclusions; + /** * @var resource */ @@ -22,6 +27,9 @@ class TMUtilMock public function __construct() { $this->stream = fopen('php://fd/' . self::DESCRIPTOR, 'a'); + + // Read any exclusions set in the environment. + $this->exclusions = explode(',', (string) getenv('KNOWN_EXCLUSIONS')); } public function __destruct() @@ -31,11 +39,20 @@ public function __destruct() public function addexclusion(string $path) { + $this->exclusions[] = $path; + fwrite($this->stream, $path . PHP_EOL); } - public function isexcluded(string $path): bool + /** + * Determines whether or not the given $path has already been excluded. + * + * @param string $path The filepath to check. + */ + public function isexcluded(string $path) { - return false; + $status = in_array($path, $this->exclusions, true) ? 'Excluded' : 'Included'; + + fwrite(STDOUT, "[$status]\t{$path}"); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 21f9a58..80eb7df 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -11,11 +11,26 @@ class TestCase extends BaseTestCase { + /** + * @var array A list of known exclusions, reset before each test. + */ + private $exclusions; + /** * @var string The temp directory that will act as our dummy home directory. */ private static $homeDir; + /** + * Reset any exclusions. + * + * @before + */ + public function resetExclusions() + { + $this->exclusions = []; + } + /** * Prepare the dummy filesystem by creating a unique directory in the temp directory. * @@ -68,6 +83,9 @@ public static function removeTempDir() /** * Execute the local copy of Asimov. * + * Asimov will use the dummy copy of tmutil, which will write the excluded paths to the + * TMUtilMock::DESCRIPTOR file descriptor, which we can then read and parse. + * * @return array An array of excluded filepaths. */ protected function asimov(): array @@ -77,8 +95,9 @@ protected function asimov(): array TMUtilMock::DESCRIPTOR => ['pipe', 'w'], ]; $env = [ - 'HOME' => self::$homeDir, - 'PATH' => __DIR__ . '/bin:' . getenv('PATH'), + 'HOME' => self::$homeDir, + 'PATH' => __DIR__ . '/bin:' . getenv('PATH'), + 'KNOWN_EXCLUSIONS' => implode(',', $this->exclusions), ]; $process = proc_open(dirname(__DIR__) . '/asimov', $descriptors, $pipes, null, $env); @@ -86,11 +105,15 @@ protected function asimov(): array trigger_error('Unable to call Asimov via proc_open().', E_USER_ERROR); } - $excluded = stream_get_contents($pipes[TMUtilMock::DESCRIPTOR]); + $excludedPaths = stream_get_contents($pipes[TMUtilMock::DESCRIPTOR]); proc_close($process); - return array_filter(explode(PHP_EOL, $excluded)); + $excludedPaths = array_filter(explode(PHP_EOL, $excludedPaths)); + + $this->exclusions = array_merge($this->exclusions, $excludedPaths); + + return $excludedPaths; } /** From 36704b1460320b373489ce4b5844a1600f484e7f Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 13:43:54 -0400 Subject: [PATCH 18/65] Add tests for the Maven exclusion pattern from #30 --- tests/AsimovTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index affa33c..5964b60 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -18,6 +18,7 @@ class AsimovTest extends TestCase * @test * @testWith ["Bower", "bower.json", "bower_components"] * ["Composer", "composer.json", "vendor"] + * ["Maven", "pom.xml", "target"] * ["Node", "package.json", "node_modules"] * ["Vagrant", "Vagrantfile", ".vagrant"] */ From 4b9dfad754e8a6dd69d9ba2a39034334641976bc Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 13:49:42 -0400 Subject: [PATCH 19/65] Remove Xdebug before running Travis CI --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index b672c59..6c7f0a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,9 @@ sudo: false php: 7.2 +before_install: + - phpenv config-rm xdebug.ini + install: - composer install --prefer-dist --no-suggest From cdeb3b045d34d6b87b458057931b646504f2fd7d Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 13:50:00 -0400 Subject: [PATCH 20/65] *Whitespace only* Reformat the composer.json file --- composer.json | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 38536d7..eb751fd 100644 --- a/composer.json +++ b/composer.json @@ -1,32 +1,32 @@ { - "name": "stevegrunwell/asimov", - "description": "Automatically exclude development dependencies from Apple Time Machine backups", - "type": "project", - "authors": [ - { - "name": "Steve Grunwell", - "homepage": "https://stevegrunwell.com" + "name": "stevegrunwell/asimov", + "description": "Automatically exclude development dependencies from Apple Time Machine backups", + "type": "project", + "authors": [ + { + "name": "Steve Grunwell", + "homepage": "https://stevegrunwell.com" + } + ], + "support": { + "source": "https://github.com/stevegrunwell/asimov", + "issues": "https://github.com/stevegrunwell/asimov/issues" + }, + "license": "MIT", + "require-dev": { + "phpunit/phpunit": "^7.3" + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "config": { + "preferred-install": "dist", + "sort-packages": true, + "optimize-autoloader": true, + "platform": { + "php": "7.2" + } } - ], - "support": { - "source": "https://github.com/stevegrunwell/asimov", - "issues": "https://github.com/stevegrunwell/asimov/issues" - }, - "license": "MIT", - "require-dev": { - "phpunit/phpunit": "^7.3" - }, - "autoload-dev": { - "psr-4": { - "Tests\\": "tests/" - } - }, - "config": { - "preferred-install": "dist", - "sort-packages": true, - "optimize-autoloader": true, - "platform": { - "php": "7.2" - } - } } From f991a5a1e153a70fa9145cc3e49ba38b8b88eb72 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 14:09:19 -0400 Subject: [PATCH 21/65] Switch to macOS for the Travis image --- .travis.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6c7f0a9..8c05a05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,10 @@ -language: php +os: osx +language: shell +sudo: false notifications: email: never -sudo: false - -php: 7.2 - -before_install: - - phpenv config-rm xdebug.ini - install: - composer install --prefer-dist --no-suggest From 1b4ad672a67722373091b48f9c523e36e9b442f6 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 14:12:25 -0400 Subject: [PATCH 22/65] Since the Travis macOS image doesn't have Composer, download the PHPUnit PHAR directly --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c05a05..560ffa7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ notifications: email: never install: - - composer install --prefer-dist --no-suggest + - wget -O phpunit https://phar.phpunit.de/phpunit-7.phar + - chmod +x phpunit + - ./phpunit --version script: - - phpunit + - ./phpunit - shellcheck asimov *.sh matrix: From fb1aa6b3cefb47c14331f2aa4b14a9e50d996c59 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 14:16:43 -0400 Subject: [PATCH 23/65] Since we need Composer to generate the autoloader, let Homebrew install it --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 560ffa7..66d239e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,11 @@ notifications: email: never install: - - wget -O phpunit https://phar.phpunit.de/phpunit-7.phar - - chmod +x phpunit - - ./phpunit --version + - brew install composer + - composer install --prefer-dist --no-suggest script: - - ./phpunit + - phpunit - shellcheck asimov *.sh matrix: From c541f319cd7a48a71b084cbe0cf1bf3febac2814 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 14:17:10 -0400 Subject: [PATCH 24/65] Also ensure that Shellcheck is present --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 66d239e..1fb1ea9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ notifications: email: never install: - - brew install composer + - brew install composer shellcheck - composer install --prefer-dist --no-suggest script: From 78344e4bb9fd49814b7741040b6639ba32c0affe Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 14 Oct 2018 14:23:15 -0400 Subject: [PATCH 25/65] Use a more explicit path to phpunit --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1fb1ea9..aaa06dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ install: - composer install --prefer-dist --no-suggest script: - - phpunit + - ./vendor/bin/phpunit - shellcheck asimov *.sh matrix: From 087459153a0da419df43e3889e0f412f89062a1e Mon Sep 17 00:00:00 2001 From: Alex K Date: Tue, 13 Nov 2018 13:47:36 +0300 Subject: [PATCH 26/65] Support Stack (Haskell) Stack is a build tool for Haskell projects. Projects managed by Stack can be identified by containing file `stack.yaml` Savings can be pretty big, excluding `.stack-work` directories saved me up to 735M per project. --- asimov | 1 + 1 file changed, 1 insertion(+) diff --git a/asimov b/asimov index 72c03a8..7e8d8f1 100755 --- a/asimov +++ b/asimov @@ -22,6 +22,7 @@ readonly FILEPATHS=( ".vagrant ../Vagrantfile" "bower_components ../bower.json" "target ../pom.xml" + ".stack-work ../stack.yaml" ) # Given a directory path, determine if the corresponding file (relative From f125b968851806ef173c46c7752ab0a8fa241d4b Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 13 Nov 2018 16:43:27 -0500 Subject: [PATCH 27/65] Add a new 'composer test' script --- composer.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/composer.json b/composer.json index eb751fd..5cfec42 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,12 @@ "Tests\\": "tests/" } }, + "scripts": { + "test": "@php vendor/bin/phpunit" + }, + "scripts-descriptions": { + "test": "Run the automated tests for Asimov." + }, "config": { "preferred-install": "dist", "sort-packages": true, From a2f40a1ed9f799349cad039c29b0d67d8b7563ae Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 13 Nov 2018 17:54:03 -0500 Subject: [PATCH 28/65] Add some nicer scripting around 'composer test' --- .travis.yml | 3 +-- composer.json | 2 +- tests/bin/run-tests.sh | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 tests/bin/run-tests.sh diff --git a/.travis.yml b/.travis.yml index aaa06dc..9116e56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,7 @@ install: - composer install --prefer-dist --no-suggest script: - - ./vendor/bin/phpunit - - shellcheck asimov *.sh + - composer test matrix: fast_finish: true diff --git a/composer.json b/composer.json index 5cfec42..2de5cda 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } }, "scripts": { - "test": "@php vendor/bin/phpunit" + "test": "sh tests/bin/run-tests.sh" }, "scripts-descriptions": { "test": "Run the automated tests for Asimov." diff --git a/tests/bin/run-tests.sh b/tests/bin/run-tests.sh new file mode 100644 index 0000000..9f77a6c --- /dev/null +++ b/tests/bin/run-tests.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env sh + +# Print a section header +section() { + printf "\\n\\033[0;36m%s\\033[0;0m\\n" "$1" +} + +# Print a warning message +notice() { + printf "\\033[0;33m%s\\033[0;0m" "$1" +} + +success() { + printf "\\033[0;32m%s\\033[0;0m\\n" "$1" +} + +section "Running unit tests:" + +if type phpunit > /dev/null; then + phpunit --testdox --colors=always || exit 1 +else + notice "PHPUnit is not installed.\\nYou may install test dependencies by running: composer install" +fi + +section "Checking coding standards:" + +if type shellcheck > /dev/null; then + shellcheck asimov ./*.sh tests/bin/run-tests.sh || exit 1 + success "No problems detected!" +else + notice "Shellcheck is not installed.\\nPlease visit https://www.shellcheck.net/ for installation options." +fi From f03fb6f4ca59ec50244b54b4a3ef64fe3283b583 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 13 Nov 2018 17:54:36 -0500 Subject: [PATCH 29/65] Use a dataProvider method rather than @testWith for patterns, as it plays nicer with --testdox --- tests/AsimovTest.php | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 5964b60..a319e75 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -9,6 +9,23 @@ class AsimovTest extends TestCase { + /** + * Data provider for known patterns. + * + * @return array An array of test scenarios. + */ + public function recognizedPatternProvider(): array + { + return [ + 'Bower' => ["bower.json", "bower_components"], + 'Composer' => ["composer.json", "vendor"], + 'Maven' => ["pom.xml", "target"], + 'Node' => ["package.json", "node_modules"], + 'Stack' => ["stack.yaml", ".stack-work"], + 'Vagrant' => ["Vagrantfile", ".vagrant"], + ]; + } + /** * A test case that catches the easiest pattern: a dependency file exists in the project * directory, and its dependencies are installed into an adjacent directory. @@ -16,17 +33,13 @@ class AsimovTest extends TestCase * When adding a simple pattern, please add it as a scenario for this test. * * @test - * @testWith ["Bower", "bower.json", "bower_components"] - * ["Composer", "composer.json", "vendor"] - * ["Maven", "pom.xml", "target"] - * ["Node", "package.json", "node_modules"] - * ["Vagrant", "Vagrantfile", ".vagrant"] + * @dataProvider recognizedPatternProvider() */ - public function it_should_exclude_dependency_directories_when_a_config_file_is_present($system, $config, $dependencies) + public function it_should_exclude_dependency_directories_when_a_config_file_is_present($config, $dependencies) { $this->createDirectoryStructure([ 'Code' => [ - "My-$system-Project" => [ + "My-Project" => [ $dependencies => [], $config => 'Configuration for this platform.', ], @@ -34,7 +47,7 @@ public function it_should_exclude_dependency_directories_when_a_config_file_is_p ]); $this->assertEquals( - [$this->getFilepath("Code/My-$system-Project/$dependencies")], + [$this->getFilepath("Code/My-Project/$dependencies")], $this->asimov(), "When a $config file is present, $dependencies/ should be excluded." ); From 6721d0119b28389eac7877b32e33ef4d915fdafd Mon Sep 17 00:00:00 2001 From: ko-dever <4114656+ko-dever@users.noreply.github.com> Date: Sun, 23 Dec 2018 12:49:53 +0000 Subject: [PATCH 30/65] Use full filepath for chmod The command `chmod +x` should use a full path to reach the file asimov. --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index bd388d6..41b251f 100755 --- a/install.sh +++ b/install.sh @@ -9,7 +9,7 @@ DIR="$(cd "$(dirname "$0")" || return; pwd -P)" PLIST="com.stevegrunwell.asimov.plist" # Verify that Asimov is executable. -chmod +x ./asimov +chmod +x "${DIR}/asimov" # Symlink Asimov into /usr/local/bin. echo -e "\\033[0;36mSymlinking ${DIR} to /usr/local/bin/asimov\\033[0m" From 11000b556cb37957f90c336392f0cee5b092ab4a Mon Sep 17 00:00:00 2001 From: Pauli Jokela Date: Wed, 2 Jan 2019 09:42:35 +0200 Subject: [PATCH 31/65] Add asimov homebrew formula asimov.rb is a homebrew formula that can be used to easily install asimov on macOS, as well as configure it to run automatically on startup. --- Formula/asimov.rb | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Formula/asimov.rb diff --git a/Formula/asimov.rb b/Formula/asimov.rb new file mode 100644 index 0000000..0d90fa5 --- /dev/null +++ b/Formula/asimov.rb @@ -0,0 +1,52 @@ +class Asimov < Formula + desc "Automatically exclude development dependencies from Apple Time Machine backups " + homepage "https://github.com/stevegrunwell/asimov" + url "https://github.com/stevegrunwell/asimov/archive/v0.2.0.tar.gz" + sha256 "2efb456975af066a17f928787062522de06c14eb322b2d133a8bc3a764cc5376" + revision 0 + + # Setup HEAD support (install with --HEAD) + head "https://github.com/stevegrunwell/asimov.git", :branch => "develop" + + # No bottling necessary + bottle :unneeded + + # Define the installation steps + def install + # Install the application + bin.install buildpath/"asimov" + end + + # Define launch agent plist options (launch automatically, but also allow manual startup) + plist_options :startup => true, :manual => "asimov" + + # Define the agent plist contents + def plist; <<~EOS + + + + + Label + #{plist_name} + Program + #{opt_bin}/asimov + StartInterval + + 86400 + + + EOS + end + + # Define tests to run + test do + # Test that the binary exists + assert File.file?(bin/"asimov"), "asimov binary not found" + + # Test that the symlink exists + assert File.file?("/usr/local/bin/asimov"), "asimov binary symlink not found in /usr/local/bin" + + # Test that the launch agent plist exists + assert File.file?(plist_path), "asimov plist not found in "+plist_path + end +end From fe8922be269a40c7ca69a81afba8aee55f53e99a Mon Sep 17 00:00:00 2001 From: Pauli Jokela Date: Wed, 2 Jan 2019 09:48:53 +0200 Subject: [PATCH 32/65] Update README.md Added installation instructions with Homebrew. --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 96fe14c..66b5f2a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,23 @@ For the average consumer, Time Machine is an excellent choice, especially consid Asimov aims to solve that problem, scanning your filesystem for known dependency directories (e.g. `node_modules/` living adjacent to a `package.json` file) and excluding them from Time Machine backups. After all, why eat up space on your backup drive for something you could easily restore via `npm install`? -## Installation +## Installation (Homebrew) + +First make sure you have [Homebrew](https://brew.sh/) installed, then run: +```sh +brew install https://raw.githubusercontent.com/stevegrunwell/asimov/develop/Formula/asimov.rb +``` + +After the installation has finished, you can enable automatic startup and scheduling: +```sh +sudo brew services start asimov +``` +or run manually: +```sh +asimov +``` + +## Installation (Manual) To get started with Asimov, clone the repository or download and extract an archive anywhere you'd like on your Mac: From ed279f396b5895b026c7b9923e14f4e361f72e90 Mon Sep 17 00:00:00 2001 From: Tae Won Ha Date: Tue, 26 Feb 2019 08:47:04 +0100 Subject: [PATCH 33/65] Exclude the Carthage folder from macOS and iOS projects --- asimov | 1 + 1 file changed, 1 insertion(+) diff --git a/asimov b/asimov index 7e8d8f1..0b07129 100755 --- a/asimov +++ b/asimov @@ -23,6 +23,7 @@ readonly FILEPATHS=( "bower_components ../bower.json" "target ../pom.xml" ".stack-work ../stack.yaml" + "Carthage ../Cartfile" ) # Given a directory path, determine if the corresponding file (relative From 05a9b2fd050fa418dedfdf8dae62aa4cfa8f10e5 Mon Sep 17 00:00:00 2001 From: Moritz Lang Date: Wed, 3 Apr 2019 22:25:15 +0200 Subject: [PATCH 34/65] Exclude Swift build files and Pods folder --- asimov | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asimov b/asimov index 0b07129..956af35 100755 --- a/asimov +++ b/asimov @@ -24,6 +24,8 @@ readonly FILEPATHS=( "target ../pom.xml" ".stack-work ../stack.yaml" "Carthage ../Cartfile" + "Pods ../Podfile" + ".build ../Package.swift" ) # Given a directory path, determine if the corresponding file (relative From c6ab96a3a313466db7ec9d1c6f672ae2f066a767 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:39:35 -0500 Subject: [PATCH 35/65] Fix minor formatting/indentation --- asimov | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asimov b/asimov index 956af35..41c6bc1 100755 --- a/asimov +++ b/asimov @@ -57,7 +57,7 @@ exclude_file() { sizeondisk=$(du -hs "$path" | cut -f1) echo "- ${path} has been excluded from Time Machine backups ($sizeondisk)." - done + done } # Start to construct the `find` parameter arguments, based on a home directory search From d0010324ffcfee01eb11c237b05f375101331d12 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:21:29 -0500 Subject: [PATCH 36/65] Consistent variable splicing style --- asimov | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/asimov b/asimov index 41c6bc1..2cf10cc 100755 --- a/asimov +++ b/asimov @@ -37,10 +37,10 @@ dependency_file_exists() { read -r path; while read -r path; do - safe_filepath_suffix=$(md5 -qs "$(basename "$path")") + safe_filepath_suffix=$(md5 -qs "$(basename "${path}")") filename="filepath_${safe_filepath_suffix}" if [ -f "${path}/${!filename}" ]; then - echo "$path" + echo "${path}" fi done } @@ -48,15 +48,15 @@ dependency_file_exists() { # Exclude the given path from Time Machine backups. exclude_file() { while read -r path; do - if tmutil isexcluded "$path" | grep -q '\[Excluded\]'; then + if tmutil isexcluded "${path}" | grep -q '\[Excluded\]'; then echo "- ${path} is already excluded, skipping." continue fi - tmutil addexclusion "$path" + tmutil addexclusion "${path}" - sizeondisk=$(du -hs "$path" | cut -f1) - echo "- ${path} has been excluded from Time Machine backups ($sizeondisk)." + sizeondisk=$(du -hs "${path}" | cut -f1) + echo "- ${path} has been excluded from Time Machine backups (${sizeondisk})." done } @@ -67,7 +67,7 @@ find_parameters=(~ -not \( -path ~/Library -prune \)) # Iterate over dependencies. n=0 for i in "${FILEPATHS[@]}"; do - read -ra parts <<< "$i" + read -ra parts <<< "${i}" # Add this folder to the `find` list, allowing a single `find` command to find all if [ "$n" -gt "0" ]; then @@ -78,7 +78,7 @@ for i in "${FILEPATHS[@]}"; do # Set up a variable for lookup in dependency_file_exists, using a hashed name # to ensure the variable name is valid safe_filepath="filepath_$(md5 -qs "${parts[0]}")" - declare "$safe_filepath"="${parts[1]}" + declare "${safe_filepath}"="${parts[1]}" ((n++)) done From 2c498484d5b24057f433f75be66d3e188a1ef392 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:29:12 -0500 Subject: [PATCH 37/65] Declare locale variables --- asimov | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/asimov b/asimov index 2cf10cc..0f1fe34 100755 --- a/asimov +++ b/asimov @@ -34,6 +34,7 @@ readonly FILEPATHS=( # For example, when looking at a /vendor directory, we may choose to # ensure a composer.json file is available. dependency_file_exists() { + local path read -r path; while read -r path; do @@ -47,6 +48,7 @@ dependency_file_exists() { # Exclude the given path from Time Machine backups. exclude_file() { + local path while read -r path; do if tmutil isexcluded "${path}" | grep -q '\[Excluded\]'; then echo "- ${path} is already excluded, skipping." @@ -62,10 +64,10 @@ exclude_file() { # Start to construct the `find` parameter arguments, based on a home directory search # but excluding ~/Library -find_parameters=(~ -not \( -path ~/Library -prune \)) +declare -a find_parameters=(~ -not \( -path ~/Library -prune \)) # Iterate over dependencies. -n=0 +declare n=0 for i in "${FILEPATHS[@]}"; do read -ra parts <<< "${i}" From 4b44523320d2c162c65639104fbaf3877b2a155b Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:29:50 -0500 Subject: [PATCH 38/65] Use grep -F instead of non-literal grep --- asimov | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asimov b/asimov index 0f1fe34..1e0b00a 100755 --- a/asimov +++ b/asimov @@ -50,7 +50,7 @@ dependency_file_exists() { exclude_file() { local path while read -r path; do - if tmutil isexcluded "${path}" | grep -q '\[Excluded\]'; then + if tmutil isexcluded "${path}" | grep -Fq '[Excluded]'; then echo "- ${path} is already excluded, skipping." continue fi From c175159dddf4bdea843042ec85bbb826fe7c27f7 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:43:27 -0500 Subject: [PATCH 39/65] Use printf instead of non-standard echo -e --- asimov | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/asimov b/asimov index 1e0b00a..9011c9a 100755 --- a/asimov +++ b/asimov @@ -85,7 +85,6 @@ for i in "${FILEPATHS[@]}"; do ((n++)) done - -echo -e "\\n\\033[0;36mFinding dependency directories with corresponding definition files...\\033[0m\\n" +printf '\n\033[0;36mFinding dependency directories with corresponding definition files…\033[0m\n' find "${find_parameters[@]}" | dependency_file_exists | exclude_file From 7c323b8f52b167f23570d00319814ad417cd955d Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:32:01 -0500 Subject: [PATCH 40/65] Ensure spaces in full paths are treated correctly --- asimov | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/asimov b/asimov index 9011c9a..5b79b8c 100755 --- a/asimov +++ b/asimov @@ -46,10 +46,11 @@ dependency_file_exists() { done } -# Exclude the given path from Time Machine backups. +# Exclude the given paths from Time Machine backups. +# Reads the newline-separated list of paths from stdin. exclude_file() { local path - while read -r path; do + while IFS=$'\n' read -r path; do if tmutil isexcluded "${path}" | grep -Fq '[Excluded]'; then echo "- ${path} is already excluded, skipping." continue From 714d592d1cd37e0a495fe123ce21a184efa57954 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:42:30 -0500 Subject: [PATCH 41/65] Enable strict bash failure flags --- asimov | 1 + 1 file changed, 1 insertion(+) diff --git a/asimov b/asimov index 5b79b8c..7198bbd 100755 --- a/asimov +++ b/asimov @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -Eeu -o pipefail # Look through the local filesystem and exclude development dependencies # from Apple Time Machine backups. From e2963d61c9abf6e002a93393e17470b484be66ee Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:38:10 -0500 Subject: [PATCH 42/65] Factor out initial directory and skip paths --- asimov | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/asimov b/asimov index 7198bbd..2e2b891 100755 --- a/asimov +++ b/asimov @@ -17,7 +17,22 @@ set -Eeu -o pipefail # @author Steve Grunwell # @license MIT -readonly FILEPATHS=( +readonly ASIMOV_ROOT=~ + +# Paths to unconditionally skip over. This prevents Asimov from modifying the +# Time Machine exclusions for these paths (and decendents). It has an important +# side-effect of speeding up the search. +readonly ASIMOV_SKIP_PATHS=( + ~/Library +) + +# A list of "directory"/"sentinel" pairs. +# Each directory will be excluded from backup iff the sentinel file exists +# alongside. +# +# For example, 'node_modules package.json' means "exclude node_modules/ from +# backup if there is a package.json next to it." +readonly ASIMOV_VENDOR_DIR_SENTINELS=( "vendor ../composer.json" "node_modules ../package.json" ".vagrant ../Vagrantfile" @@ -64,13 +79,17 @@ exclude_file() { done } -# Start to construct the `find` parameter arguments, based on a home directory search -# but excluding ~/Library -declare -a find_parameters=(~ -not \( -path ~/Library -prune \)) +# Start to construct the `find` parameter arguments, based on an initial directory. +declare -a find_parameters=("${ASIMOV_ROOT}") + +# Iterate over the skip directories to construct the `find` expression. +for d in "${ASIMOV_SKIP_PATHS[@]}"; do + find_parameters+=( -not \( -path "${d}" -prune \) ) +done # Iterate over dependencies. declare n=0 -for i in "${FILEPATHS[@]}"; do +for i in "${ASIMOV_VENDOR_DIR_SENTINELS[@]}"; do read -ra parts <<< "${i}" # Add this folder to the `find` list, allowing a single `find` command to find all From c2b7a7108e1169e4289f28a8297830e54aa26b69 Mon Sep 17 00:00:00 2001 From: Robert Estelle Date: Thu, 31 Jan 2019 13:41:09 -0500 Subject: [PATCH 43/65] Test for sibling sentinel file via find -execdir This allows the paths to be pruned more quickly and reduces the need for the md5-variable-name juggling. --- asimov | 76 ++++++++++++++++++++++++---------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/asimov b/asimov index 2e2b891..0de8dca 100755 --- a/asimov +++ b/asimov @@ -33,35 +33,17 @@ readonly ASIMOV_SKIP_PATHS=( # For example, 'node_modules package.json' means "exclude node_modules/ from # backup if there is a package.json next to it." readonly ASIMOV_VENDOR_DIR_SENTINELS=( - "vendor ../composer.json" - "node_modules ../package.json" - ".vagrant ../Vagrantfile" - "bower_components ../bower.json" - "target ../pom.xml" - ".stack-work ../stack.yaml" - "Carthage ../Cartfile" - "Pods ../Podfile" - ".build ../Package.swift" + '.build Package.swift' + '.stack-work stack.yaml' + '.vagrant Vagrantfile' + 'Carthage Cartfile' + 'Pods Podfile' + 'bower_components bower.json' + 'node_modules package.json' + 'target pom.xml' + 'vendor composer.json' ) -# Given a directory path, determine if the corresponding file (relative -# to that directory) is available. -# -# For example, when looking at a /vendor directory, we may choose to -# ensure a composer.json file is available. -dependency_file_exists() { - local path - read -r path; - - while read -r path; do - safe_filepath_suffix=$(md5 -qs "$(basename "${path}")") - filename="filepath_${safe_filepath_suffix}" - if [ -f "${path}/${!filename}" ]; then - echo "${path}" - fi - done -} - # Exclude the given paths from Time Machine backups. # Reads the newline-separated list of paths from stdin. exclude_file() { @@ -79,33 +61,37 @@ exclude_file() { done } -# Start to construct the `find` parameter arguments, based on an initial directory. -declare -a find_parameters=("${ASIMOV_ROOT}") - # Iterate over the skip directories to construct the `find` expression. +declare -a find_parameters_skip=() for d in "${ASIMOV_SKIP_PATHS[@]}"; do - find_parameters+=( -not \( -path "${d}" -prune \) ) + find_parameters_skip+=( -not \( -path "${d}" -prune \) ) done -# Iterate over dependencies. -declare n=0 +# Iterate over the directory/sentinel pairs to construct the `find` expression. +declare -a find_parameters_vendor=() for i in "${ASIMOV_VENDOR_DIR_SENTINELS[@]}"; do read -ra parts <<< "${i}" # Add this folder to the `find` list, allowing a single `find` command to find all - if [ "$n" -gt "0" ]; then - find_parameters+=(-o) - fi - find_parameters+=(-name "${parts[0]}" -type d -prune) - - # Set up a variable for lookup in dependency_file_exists, using a hashed name - # to ensure the variable name is valid - safe_filepath="filepath_$(md5 -qs "${parts[0]}")" - declare "${safe_filepath}"="${parts[1]}" - - ((n++)) + _exclude_name="${parts[0]}" + _sibling_sentinel_name="${parts[1]}" + + # Given a directory path, determine if the corresponding file (relative + # to that directory) is available. + # + # For example, when looking at a /vendor directory, we may choose to + # ensure a composer.json file is available. + find_parameters_vendor+=( -or \( \ + -type d \ + -name "${_exclude_name}" \ + -execdir test -e "${_sibling_sentinel_name}" \; \ + -prune \ + -print \ + \) ) done printf '\n\033[0;36mFinding dependency directories with corresponding definition files…\033[0m\n' -find "${find_parameters[@]}" | dependency_file_exists | exclude_file +find "${ASIMOV_ROOT}" \( "${find_parameters_skip[@]}" \) \( -false "${find_parameters_vendor[@]}" \) \ + | exclude_file \ + ; From e7c4da3fe63cc9edc8e270891d33cfc1084ea8aa Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Sun, 1 Mar 2020 12:24:26 +0800 Subject: [PATCH 44/65] README: clone https, not ssh When one has a pubkey set up, ssh clone with the user "git" often effs up. This commit changes to HTTPS clone with a depth argument in case the repo gets large in the future. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96fe14c..79de2c6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Asimov aims to solve that problem, scanning your filesystem for known dependency To get started with Asimov, clone the repository or download and extract an archive anywhere you'd like on your Mac: ```sh -$ git clone git@github.com:stevegrunwell/asimov.git +$ git clone https://github.com/stevegrunwell/asimov.git --depth 1 ``` After you've cloned the repository, run the `install.sh` script to automatically: From 3288173b1acacabcc35fddd507c6306330943909 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 13:50:58 -0400 Subject: [PATCH 45/65] Fix coding standards to comply with 'brew audit --new-formula' --- Formula/asimov.rb | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Formula/asimov.rb b/Formula/asimov.rb index 0d90fa5..8894caa 100644 --- a/Formula/asimov.rb +++ b/Formula/asimov.rb @@ -1,5 +1,5 @@ class Asimov < Formula - desc "Automatically exclude development dependencies from Apple Time Machine backups " + desc "Automatically exclude development dependencies from Time Machine backups" homepage "https://github.com/stevegrunwell/asimov" url "https://github.com/stevegrunwell/asimov/archive/v0.2.0.tar.gz" sha256 "2efb456975af066a17f928787062522de06c14eb322b2d133a8bc3a764cc5376" @@ -21,21 +21,22 @@ def install plist_options :startup => true, :manual => "asimov" # Define the agent plist contents - def plist; <<~EOS - - - - - Label - #{plist_name} - Program - #{opt_bin}/asimov - StartInterval - - 86400 - - - EOS + def plist + <<~EOS + + + + + Label + #{plist_name} + Program + #{opt_bin}/asimov + StartInterval + + 86400 + + + EOS end # Define tests to run From 947989eccf282085ddd385e68c18f25db032e6c6 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 15:13:33 -0400 Subject: [PATCH 46/65] Refresh the tests to a) use PHPUnit 9 and b) include the currently-defined patterns --- asimov | 26 +- composer.json | 12 +- composer.lock | 861 +++++++++++++++++++++++++++++-------------- tests/AsimovTest.php | 17 +- 4 files changed, 612 insertions(+), 304 deletions(-) diff --git a/asimov b/asimov index 0de8dca..36cc905 100755 --- a/asimov +++ b/asimov @@ -27,21 +27,21 @@ readonly ASIMOV_SKIP_PATHS=( ) # A list of "directory"/"sentinel" pairs. -# Each directory will be excluded from backup iff the sentinel file exists -# alongside. # -# For example, 'node_modules package.json' means "exclude node_modules/ from -# backup if there is a package.json next to it." +# Directories will only be excluded if the dependency ("sentinel") file exists. +# +# For example, 'node_modules package.json' means "exclude node_modules/ from the +# Time Machine backups if there is a package.json file next to it." readonly ASIMOV_VENDOR_DIR_SENTINELS=( - '.build Package.swift' - '.stack-work stack.yaml' - '.vagrant Vagrantfile' - 'Carthage Cartfile' - 'Pods Podfile' - 'bower_components bower.json' - 'node_modules package.json' - 'target pom.xml' - 'vendor composer.json' + '.build Package.swift' # Swift + '.stack-work stack.yaml' # Stack (Haskell) + '.vagrant Vagrantfile' # Vagrant + 'Carthage Cartfile' # Carthage + 'Pods Podfile' # CocoaPods + 'bower_components bower.json' # Bower + 'node_modules package.json' # NodeJS + 'target pom.xml' # Maven + 'vendor composer.json' # Composer ) # Exclude the given paths from Time Machine backups. diff --git a/composer.json b/composer.json index 2de5cda..622a53f 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,10 @@ { "name": "Steve Grunwell", "homepage": "https://stevegrunwell.com" + }, + { + "name": "Sudar Muthu", + "homepage": "https://sudarmuthu.com" } ], "support": { @@ -14,7 +18,7 @@ }, "license": "MIT", "require-dev": { - "phpunit/phpunit": "^7.3" + "phpunit/phpunit": "^9.0" }, "autoload-dev": { "psr-4": { @@ -29,10 +33,6 @@ }, "config": { "preferred-install": "dist", - "sort-packages": true, - "optimize-autoloader": true, - "platform": { - "php": "7.2" - } + "sort-packages": true } } diff --git a/composer.lock b/composer.lock index 2ac5532..d759ea7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,32 +4,34 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "24a76b63a6599632bb89a5ab94236f91", + "content-hash": "64eff0b6a6f6077c2095514c079d8357", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.1.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { @@ -54,25 +56,39 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2017-07-22T11:58:36+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-05-29T17:27:14+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.8.1", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", "shasum": "" }, "require": { @@ -107,7 +123,7 @@ "object", "object graph" ], - "time": "2018-06-11T23:09:50+00:00" + "time": "2020-01-17T21:11:47+00:00" }, { "name": "phar-io/manifest", @@ -213,35 +229,30 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "shasum": "" }, "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -263,44 +274,42 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2020-04-27T09:25:28+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -311,44 +320,46 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.2", + "mockery/mockery": "~1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -361,42 +372,43 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2020-02-18T18:59:58+00:00" }, { "name": "phpspec/prophecy", - "version": "1.8.0", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", + "phpspec/phpspec": "^2.5 || ^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -424,44 +436,45 @@ "spy", "stub" ], - "time": "2018-08-05T17:53:17+00:00" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "6.0.7", + "version": "8.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a" + "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/865662550c384bc1db7e51d29aeda1c2c161d69a", - "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca6647ffddd2add025ab3f21644a441d7c146cdc", + "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "php": "^7.3", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-token-stream": "^4.0", + "sebastian/code-unit-reverse-lookup": "^2.0", + "sebastian/environment": "^5.0", + "sebastian/version": "^3.0", + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.0" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "8.0-dev" } }, "autoload": { @@ -487,29 +500,38 @@ "testing", "xunit" ], - "time": "2018-06-01T07:51:50+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-05-23T08:02:54+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.1", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c" + "reference": "4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c", - "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4", + "reference": "4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -534,26 +556,90 @@ "filesystem", "iterator" ], - "time": "2018-06-11T11:44:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-04-18T05:02:12+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/7579d5a1ba7f3ac11c80004d205877911315ae7a", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "time": "2020-02-07T06:06:11+00:00" }, { "name": "phpunit/php-text-template", - "version": "1.2.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/526dc996cc0ebdfa428cd2dfccd79b7b53fee346", + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -575,32 +661,32 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2020-02-01T07:43:44+00:00" }, { "name": "phpunit/php-timer", - "version": "2.0.0", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" + "reference": "b0d089de001ba60ffa3be36b23e1b8150d072238" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", - "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/b0d089de001ba60ffa3be36b23e1b8150d072238", + "reference": "b0d089de001ba60ffa3be36b23e1b8150d072238", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -624,33 +710,39 @@ "keywords": [ "timer" ], - "time": "2018-02-01T13:07:23+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-06-07T12:05:53+00:00" }, { "name": "phpunit/php-token-stream", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" + "reference": "cdc0db5aed8fbfaf475fbd95bfd7bab83c7a779c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", - "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/cdc0db5aed8fbfaf475fbd95bfd7bab83c7a779c", + "reference": "cdc0db5aed8fbfaf475fbd95bfd7bab83c7a779c", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.1" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -673,57 +765,64 @@ "keywords": [ "tokenizer" ], - "time": "2018-02-01T13:16:43+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-05-06T09:56:31+00:00" }, { "name": "phpunit/phpunit", - "version": "7.3.3", + "version": "9.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898" + "reference": "8fd0d8f80029682da89516a554f4d5f5a030345c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", - "reference": "1bd5629cccfb2c0a9ef5474b4ff772349e1ec898", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8fd0d8f80029682da89516a554f4d5f5a030345c", + "reference": "8fd0d8f80029682da89516a554f4d5f5a030345c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.1", + "doctrine/instantiator": "^1.2.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.0", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.3", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^8.0.1", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-invoker": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-timer": "^5.0", + "sebastian/code-unit": "^1.0.2", + "sebastian/comparator": "^4.0", + "sebastian/diff": "^4.0", + "sebastian/environment": "^5.0.1", + "sebastian/exporter": "^4.0", + "sebastian/global-state": "^4.0", + "sebastian/object-enumerator": "^4.0", + "sebastian/resource-operations": "^3.0", + "sebastian/type": "^2.1", + "sebastian/version": "^3.0" }, "require-dev": { - "ext-pdo": "*" + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0" }, "suggest": { "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "ext-xdebug": "*" }, "bin": [ "phpunit" @@ -731,12 +830,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.3-dev" + "dev-master": "9.2-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -757,32 +859,94 @@ "testing", "xunit" ], - "time": "2018-09-01T15:49:55+00:00" + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-06-07T14:14:21+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "ac958085bc19fcd1d36425c781ef4cbb5b06e2a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ac958085bc19fcd1d36425c781ef4cbb5b06e2a5", + "reference": "ac958085bc19fcd1d36425c781ef4cbb5b06e2a5", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-04-30T05:58:10+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5b5dbe0044085ac41df47e79d34911a15b96d82e", + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -802,34 +966,34 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "time": "2020-02-07T06:20:13+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85b3435da967696ed618ff745f32be3ff4a2b8e8", + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8", "shasum": "" }, "require": { - "php": "^7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" + "php": "^7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -842,6 +1006,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -853,10 +1021,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -866,33 +1030,33 @@ "compare", "equality" ], - "time": "2018-07-12T15:12:46+00:00" + "time": "2020-02-07T06:08:51+00:00" }, { "name": "sebastian/diff", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "366541b989927187c4ca70490a35615d3fef2dce" + "reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", - "reference": "366541b989927187c4ca70490a35615d3fef2dce", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3e523c576f29dacecff309f35e4cc5a5c168e78a", + "reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^7.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -905,13 +1069,13 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", @@ -922,32 +1086,41 @@ "unidiff", "unified diff" ], - "time": "2018-06-10T07:54:39+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-05-08T05:01:12+00:00" }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "c753f04d68cd489b6973cf9b4e505e191af3b05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/c753f04d68cd489b6973cf9b4e505e191af3b05c", + "reference": "c753f04d68cd489b6973cf9b4e505e191af3b05c", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -972,34 +1145,40 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-04-14T13:36:52+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "80c26562e964016538f832f305b2286e1ec29566" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/80c26562e964016538f832f305b2286e1ec29566", + "reference": "80c26562e964016538f832f305b2286e1ec29566", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1012,6 +1191,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1020,17 +1203,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1039,27 +1218,30 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2020-02-07T06:10:52+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bdb1e7c79e592b8c82cb1699be3c8743119b8a72", + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.0" }, "suggest": { "ext-uopz": "*" @@ -1067,7 +1249,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1090,34 +1272,34 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2020-02-07T06:11:37+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "e67516b175550abad905dc952f43285957ef4363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67516b175550abad905dc952f43285957ef4363", + "reference": "e67516b175550abad905dc952f43285957ef4363", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1137,32 +1319,32 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "time": "2020-02-07T06:12:23+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1182,32 +1364,32 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "time": "2020-02-07T06:19:40+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "cdd86616411fc3062368b720b0425de10bd3d579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cdd86616411fc3062368b720b0425de10bd3d579", + "reference": "cdd86616411fc3062368b720b0425de10bd3d579", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1220,14 +1402,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -1235,29 +1417,32 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "time": "2020-02-07T06:18:20+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1277,29 +1462,81 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "time": "2020-02-07T06:13:02+00:00" + }, + { + "name": "sebastian/type", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8", + "reference": "bad49207c6f854e7a25cef0ea948ac8ebe3ef9d8", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-06-01T12:21:09+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "0411bde656dce64202b39c2f4473993a9081d39e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/0411bde656dce64202b39c2f4473993a9081d39e", + "reference": "0411bde656dce64202b39c2f4473993a9081d39e", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1320,20 +1557,92 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "time": "2020-01-21T06:36:37+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:14:59+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", "shasum": "" }, "require": { @@ -1360,35 +1669,33 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" + "time": "2019-06-13T22:48:21+00:00" }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "vimeo/psalm": "<3.9.1" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -1410,7 +1717,7 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2020-04-18T12:12:48+00:00" } ], "aliases": [], @@ -1420,7 +1727,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "platform-overrides": { - "php": "7.2" - } + "plugin-api-version": "1.1.0" } diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index a319e75..0e70dbc 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -12,17 +12,20 @@ class AsimovTest extends TestCase /** * Data provider for known patterns. * - * @return array An array of test scenarios. + * @return array[] An array of test scenarios, in the form of "sentinel => directory". */ public function recognizedPatternProvider(): array { return [ - 'Bower' => ["bower.json", "bower_components"], - 'Composer' => ["composer.json", "vendor"], - 'Maven' => ["pom.xml", "target"], - 'Node' => ["package.json", "node_modules"], - 'Stack' => ["stack.yaml", ".stack-work"], - 'Vagrant' => ["Vagrantfile", ".vagrant"], + 'Bower' => ['bower.json', 'bower_components'], + 'Carthage' => ['Cartfile', 'Carthage'], + 'CocoaPods' => ['Podfile', 'Pods'], + 'Composer' => ['composer.json', 'vendor'], + 'Maven' => ['pom.xml', 'target'], + 'Node' => ['package.json', 'node_modules'], + 'Stack' => ['stack.yaml', '.stack-work'], + 'Swift' => ['Package.swift', '.build'], + 'Vagrant' => ['Vagrantfile', '.vagrant'], ]; } From 95a9cf73850ddb169495023e9e517013b21ceba4 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 15:48:11 -0400 Subject: [PATCH 47/65] Clean up the Travis test matrix --- .travis.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9116e56..68e3761 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,15 @@ os: osx language: shell -sudo: false -notifications: - email: never +matrix: + include: + - name: macOS 10.15 (Catalina) + osx_image: xcode11.5 + - name: macOS 10.14 (Mojave) + osx_image: xcode11.3 + - name: macOS 10.13 (High Sierra) + osx_image: xcode10.1 + fast_finish: true install: - brew install composer shellcheck @@ -11,6 +17,3 @@ install: script: - composer test - -matrix: - fast_finish: true From 19ac78921ed92d105aec4a6f1bd82d1ab46d9c9e Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 15:50:23 -0400 Subject: [PATCH 48/65] Ensure we have PHP 7.3 available, as it's required for PHPUnit 9.x --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 68e3761..84a8e94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: fast_finish: true install: - - brew install composer shellcheck + - brew install composer php7.3 shellcheck - composer install --prefer-dist --no-suggest script: From 45ca32db9321eb53e5bc42233a5760f4ef725d85 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 15:52:20 -0400 Subject: [PATCH 49/65] Use develop, not master, as the build status badge in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b0d53c..50f1e36 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Asimov -[![Build Status](https://travis-ci.com/stevegrunwell/asimov.svg?branch=master)](https://travis-ci.com/stevegrunwell/asimov) +[![Build Status](https://travis-ci.com/stevegrunwell/asimov.svg?branch=develop)](https://travis-ci.com/stevegrunwell/asimov) > Those people who think they know everything are a great annoyance to those of us who do.
— Issac Asimov From a9e0e7ca736a80aaa76a159a0cffc2f8e6c973e9 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 15:54:07 -0400 Subject: [PATCH 50/65] Homebrew now requires php@version as the syntax --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 84a8e94..2b37083 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: fast_finish: true install: - - brew install composer php7.3 shellcheck + - brew install composer php@7.3 shellcheck - composer install --prefer-dist --no-suggest script: From 40a03be17d1789603e702bff5e476669dc2a85cb Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 16:28:19 -0400 Subject: [PATCH 51/65] Allow the CI pipeline to use PHPUnit 8 or 9 so we don't have to explicitly install a newer PHP version --- .gitignore | 1 + .travis.yml | 3 ++- composer.json | 5 ++++- composer.lock | 6 ++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 85d346a..8d95b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ vendor .DS_Store +.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml index 2b37083..1dad747 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,8 @@ matrix: fast_finish: true install: - - brew install composer php@7.3 shellcheck + - brew install composer shellcheck + - composer check-platform-reqs - composer install --prefer-dist --no-suggest script: diff --git a/composer.json b/composer.json index 622a53f..7b4501d 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,11 @@ "issues": "https://github.com/stevegrunwell/asimov/issues" }, "license": "MIT", + "require": { + "php": ">=7.2" + }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^8.0|^9.0" }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index d759ea7..443bfea 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "64eff0b6a6f6077c2095514c079d8357", + "content-hash": "26ba31e9c36ddc0cdc2d3fc036b24709", "packages": [], "packages-dev": [ { @@ -1725,7 +1725,9 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": ">=7.2" + }, "platform-dev": [], "plugin-api-version": "1.1.0" } From 42608ca6d37921a5e0c0e1433b8b75fb74eee3e1 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 21:21:23 -0400 Subject: [PATCH 52/65] Since macOS < 10.15 ship with dead versions of PHP (7.1, it seems), let these environments use older versions of PHPUnit for the sake of automated testing --- composer.json | 4 ++-- composer.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 7b4501d..838c17d 100644 --- a/composer.json +++ b/composer.json @@ -18,10 +18,10 @@ }, "license": "MIT", "require": { - "php": ">=7.2" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^8.0|^9.0" + "phpunit/phpunit": "^7.5|^8.5|^9.0" }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index 443bfea..28bc426 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "26ba31e9c36ddc0cdc2d3fc036b24709", + "content-hash": "0d088b009a676693f542adc6b89202ee", "packages": [], "packages-dev": [ { @@ -1726,7 +1726,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.2" + "php": ">=7.1" }, "platform-dev": [], "plugin-api-version": "1.1.0" From f5ee6a48478a7fa98380bea6d312d41693c40a3f Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 21:22:46 -0400 Subject: [PATCH 53/65] Clean up the existing changelog entries --- CHANGELOG.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b374cc..a002d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,22 +5,29 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [0.2.0] +## [Version 0.2.0] — 2017-11-25 + +### Added * Bundle the script with `com.stevegrunwell.asimov.plist`, enabling Asimov to be scheduled to run daily. Users can set this up in a single step by running the new `install.sh` script. -* Fixed pathing issue when resolving the script directory for `install.sh`. Props @morganestes. (#7) -* Change the scope of Asimov to find matching directories within the current user's home directory, not just `~/Sites`. Props to @vitch for catching this! (#10). -* Added a formal change log to the repository. (#5) + Added a formal change log to the repository. ([#5]) + +### Fixed + +* Fixed pathing issue when resolving the script directory for `install.sh`. Props @morganestes. ([#7]) +### Changed +* Change the scope of Asimov to find matching directories within the current user's home directory, not just `~/Sites`. Props to @vitch for catching this! ([#10]). -## [0.1.0] + +## [Version 0.1.0] — 2017-10-17 Initial public release. [Unreleased]: https://github.com/stevegrunwell/asimov/compare/master...develop -[0.2.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.2.0 -[0.1.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.1.0 -[#10]: https://github.com/stevegrunwell/asimov/issues/10 +[Version 0.1.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.1.0 +[Version 0.2.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.2.0 +[#5]: https://github.com/stevegrunwell/asimov/issues/5 [#7]: https://github.com/stevegrunwell/asimov/issues/7 -[#5]: https://github.com/stevegrunwell/asimov/issues/5 \ No newline at end of file +[#10]: https://github.com/stevegrunwell/asimov/issues/10 From 7c4b04ef2305fd98ac76e79766acf20d0d97f174 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 21:43:58 -0400 Subject: [PATCH 54/65] Update the CHANGELOG.md file with everything that's happened (so far) --- CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a002d25..752b51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Added + +* Added Homebrew support 🙌 ([#34], props @Dids) +* Exclude Bower dependencies ([#22], props @moezzie) +* Exclude Maven builds ([#30], props @bertschneider) +* Exclude Stack dependencies ([#32], props @alex-kononovich) +* Exclude Carthage dependencies ([#37], props @qvacua) +* Exclude CocoaPods dependencies and Swift builds ([#43], props @slashmo) +* Define a [Travis CI pipeline for Asimov](https://travis-ci.com/github/stevegrunwell/asimov) ([#20]) + +### Fixed + +* Removed an extraneous `read -r path`, which was causing the first match to be skipped ([#15], props @rowanbeentje) +* Use the full system path when running `chmod` in `install.sh` ([#33], props @ko-dever) + +### Changed + +* The size of the excluded directories are now included in the Asimov output ([#16], props @rowanbeentje) +* Switch to using find's -prune switch to exclude match subdirectories for speed, and exclude ~/Library folder from searches ([#17], props @rowanbeentje) +* Rework the `find` command and path variables so that `find` is only run once however many FILEPATHS are set ([#18], @props @rowanbeentje, yet again 😉) + Fix incorrect directory pruning, simplify path handling ([#36], props @rwe) +* Recommend cloning via HTTPS rather than SSH for manual installations ([#52], props @Artoria2e5) + ## [Version 0.2.0] — 2017-11-25 @@ -31,3 +56,17 @@ Initial public release. [#5]: https://github.com/stevegrunwell/asimov/issues/5 [#7]: https://github.com/stevegrunwell/asimov/issues/7 [#10]: https://github.com/stevegrunwell/asimov/issues/10 +[#15]: https://github.com/stevegrunwell/asimov/pull/15 +[#16]: https://github.com/stevegrunwell/asimov/pull/16 +[#17]: https://github.com/stevegrunwell/asimov/pull/17 +[#18]: https://github.com/stevegrunwell/asimov/pull/18 +[#20]: https://github.com/stevegrunwell/asimov/pull/20 +[#22]: https://github.com/stevegrunwell/asimov/pull/22 +[#30]: https://github.com/stevegrunwell/asimov/pull/30 +[#32]: https://github.com/stevegrunwell/asimov/pull/32 +[#33]: https://github.com/stevegrunwell/asimov/pull/33 +[#34]: https://github.com/stevegrunwell/asimov/pull/34 +[#36]: https://github.com/stevegrunwell/asimov/pull/36 +[#37]: https://github.com/stevegrunwell/asimov/pull/37 +[#43]: https://github.com/stevegrunwell/asimov/pull/43 +[#52]: https://github.com/stevegrunwell/asimov/pull/52 From 635ebdaea310db62729bac3049c5e0d7d0e1ceb2 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:10:50 -0400 Subject: [PATCH 55/65] When running the CI pipeline, if the current PHP version is older than 7.3 (required for PHPUnit 9.x), run 'composer update --prefer-lowest' to get the older versions --- .editorconfig | 3 ++- .travis.yml | 8 ++++++-- composer.json | 2 +- composer.lock | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.editorconfig b/.editorconfig index 5d68a00..9938b26 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,4 @@ +# https://editorconfig.org root = true [*] @@ -8,7 +9,7 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.php] +[*.{json,php}] indent_size = 4 [*.yml] diff --git a/.travis.yml b/.travis.yml index 1dad747..869c31b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,12 @@ matrix: install: - brew install composer shellcheck - - composer check-platform-reqs - - composer install --prefer-dist --no-suggest + - | + if [[ $(php -r 'echo phpversion() . PHP_EOL;') < 7.3.1 ]]; then + composer update --prefer-lowest --prefer-dist --no-suggest --no-progress --no-ansi + else + composer install --prefer-dist --no-suggest --no-progress --no-ansi + fi script: - composer test diff --git a/composer.json b/composer.json index 838c17d..505d17c 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.5|^8.5|^9.0" + "phpunit/phpunit": "^7.5|^9.0" }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index 28bc426..cf313f7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0d088b009a676693f542adc6b89202ee", + "content-hash": "b84c992e520a41893c750619a5bf4047", "packages": [], "packages-dev": [ { From a2c0ed29f0e6becf217e421a3b3ffc1843bdeb6a Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:17:59 -0400 Subject: [PATCH 56/65] Add a changelog entry for #31 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 752b51d..5bbc1eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Exclude Carthage dependencies ([#37], props @qvacua) * Exclude CocoaPods dependencies and Swift builds ([#43], props @slashmo) * Define a [Travis CI pipeline for Asimov](https://travis-ci.com/github/stevegrunwell/asimov) ([#20]) +* Add an automated test suite using PHPUnit ([#31]) ### Fixed @@ -63,6 +64,7 @@ Initial public release. [#20]: https://github.com/stevegrunwell/asimov/pull/20 [#22]: https://github.com/stevegrunwell/asimov/pull/22 [#30]: https://github.com/stevegrunwell/asimov/pull/30 +[#31]: https://github.com/stevegrunwell/asimov/pull/31 [#32]: https://github.com/stevegrunwell/asimov/pull/32 [#33]: https://github.com/stevegrunwell/asimov/pull/33 [#34]: https://github.com/stevegrunwell/asimov/pull/34 From 339e3cd04389b150673fb38e9fde0c8674ce9707 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:33:54 -0400 Subject: [PATCH 57/65] Skip the user's ~/.Trash directory Ideally, Time Machine will already be ignoring the trash, but we shoudln't need to spend time going through it. Fixes #47. --- asimov | 1 + tests/AsimovTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/asimov b/asimov index 36cc905..ba915d4 100755 --- a/asimov +++ b/asimov @@ -23,6 +23,7 @@ readonly ASIMOV_ROOT=~ # Time Machine exclusions for these paths (and decendents). It has an important # side-effect of speeding up the search. readonly ASIMOV_SKIP_PATHS=( + ~/.Trash ~/Library ) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 0e70dbc..6c21f6d 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -112,4 +112,28 @@ public function it_should_only_exclude_new_matches() 'Asimov should not have found any new paths on the second run.' ); } + + /** + * @test + * @ticket https://github.com/stevegrunwell/asimov/issues/47 + * @runInSeparateProcess + */ + public function it_should_not_check_a_users_trash_directory() + { + $this->createDirectoryStructure([ + '.Trash' => [ + 'My-Project' => [ + 'vendor' => [], + 'composer.json' => 'Configuration for this platform.', + ], + ], + ]); + + putenv('HOME=' . $this->getFilepath('/')); + + $this->assertEmpty( + $this->asimov(), + 'Asimov should not have been checking the ~/.Trash directory.' + ); + } } From 52f612845dcb27e87b4c6fc5307ec5bfd6e5972f Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:35:47 -0400 Subject: [PATCH 58/65] Add a changelog entry for #55 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbc1eb..d53ef6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Rework the `find` command and path variables so that `find` is only run once however many FILEPATHS are set ([#18], @props @rowanbeentje, yet again 😉) Fix incorrect directory pruning, simplify path handling ([#36], props @rwe) * Recommend cloning via HTTPS rather than SSH for manual installations ([#52], props @Artoria2e5) +* Don't look for matches in `~/.Trash` ([#55]) ## [Version 0.2.0] — 2017-11-25 @@ -72,3 +73,4 @@ Initial public release. [#37]: https://github.com/stevegrunwell/asimov/pull/37 [#43]: https://github.com/stevegrunwell/asimov/pull/43 [#52]: https://github.com/stevegrunwell/asimov/pull/52 +[#55]: https://github.com/stevegrunwell/asimov/pull/55 From 1642a77fb5e6f106c0e80c1c24e2a0c612e82a82 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:47:45 -0400 Subject: [PATCH 59/65] Add Rust's Cargo tool Docs: https://doc.rust-lang.org/cargo/guide/creating-a-new-project.html --- asimov | 1 + tests/AsimovTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/asimov b/asimov index 36cc905..2c079cc 100755 --- a/asimov +++ b/asimov @@ -36,6 +36,7 @@ readonly ASIMOV_VENDOR_DIR_SENTINELS=( '.build Package.swift' # Swift '.stack-work stack.yaml' # Stack (Haskell) '.vagrant Vagrantfile' # Vagrant + 'target Cargo.toml' # Cargo (Rust) 'Carthage Cartfile' # Carthage 'Pods Podfile' # CocoaPods 'bower_components bower.json' # Bower diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 0e70dbc..db0d15f 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -18,6 +18,7 @@ public function recognizedPatternProvider(): array { return [ 'Bower' => ['bower.json', 'bower_components'], + 'Cargo' => ['Cargo.toml', 'target'], 'Carthage' => ['Cartfile', 'Carthage'], 'CocoaPods' => ['Podfile', 'Pods'], 'Composer' => ['composer.json', 'vendor'], From 403cd79bdc861cd5fb6d4c06ae48d1eb6b993ec0 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 22:52:18 -0400 Subject: [PATCH 60/65] Exclude Dart's .packages directory Documentation: https://dart.dev/guides/packages --- asimov | 1 + tests/AsimovTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/asimov b/asimov index 2c079cc..bdaf40e 100755 --- a/asimov +++ b/asimov @@ -34,6 +34,7 @@ readonly ASIMOV_SKIP_PATHS=( # Time Machine backups if there is a package.json file next to it." readonly ASIMOV_VENDOR_DIR_SENTINELS=( '.build Package.swift' # Swift + '.packages pubspec.yaml' # Pub (Dart) '.stack-work stack.yaml' # Stack (Haskell) '.vagrant Vagrantfile' # Vagrant 'target Cargo.toml' # Cargo (Rust) diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index db0d15f..61dc8bc 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -22,6 +22,7 @@ public function recognizedPatternProvider(): array 'Carthage' => ['Cartfile', 'Carthage'], 'CocoaPods' => ['Podfile', 'Pods'], 'Composer' => ['composer.json', 'vendor'], + 'Dart' => ['pubspec.yaml', '.packages'], 'Maven' => ['pom.xml', 'target'], 'Node' => ['package.json', 'node_modules'], 'Stack' => ['stack.yaml', '.stack-work'], From eba48c5f2d385b82a61da8a6062e28ea1866f9e4 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 23:15:05 -0400 Subject: [PATCH 61/65] Add Bundler to the list of dependency patterns --- asimov | 9 +++++---- tests/AsimovTest.php | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/asimov b/asimov index bdaf40e..39f3615 100755 --- a/asimov +++ b/asimov @@ -37,13 +37,14 @@ readonly ASIMOV_VENDOR_DIR_SENTINELS=( '.packages pubspec.yaml' # Pub (Dart) '.stack-work stack.yaml' # Stack (Haskell) '.vagrant Vagrantfile' # Vagrant - 'target Cargo.toml' # Cargo (Rust) 'Carthage Cartfile' # Carthage 'Pods Podfile' # CocoaPods - 'bower_components bower.json' # Bower - 'node_modules package.json' # NodeJS + 'bower_components bower.json' # Bower (JavaScript) + 'node_modules package.json' # npm, Yarn (NodeJS) + 'target Cargo.toml' # Cargo (Rust) 'target pom.xml' # Maven - 'vendor composer.json' # Composer + 'vendor composer.json' # Composer (PHP) + 'vendor Gemfile' # Bundler (Ruby) ) # Exclude the given paths from Time Machine backups. diff --git a/tests/AsimovTest.php b/tests/AsimovTest.php index 61dc8bc..c5d6bb3 100644 --- a/tests/AsimovTest.php +++ b/tests/AsimovTest.php @@ -18,6 +18,7 @@ public function recognizedPatternProvider(): array { return [ 'Bower' => ['bower.json', 'bower_components'], + 'Bundler' => ['Gemfile', 'vendor'], 'Cargo' => ['Cargo.toml', 'target'], 'Carthage' => ['Cartfile', 'Carthage'], 'CocoaPods' => ['Podfile', 'Pods'], From 0b86d6ddd20c986f76fad1bd4b785115ead8c58d Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Sun, 7 Jun 2020 23:18:37 -0400 Subject: [PATCH 62/65] Add a changelog entry for the Bundler, Cargo, and Dart exclusions --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d53ef6f..1349d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Exclude Stack dependencies ([#32], props @alex-kononovich) * Exclude Carthage dependencies ([#37], props @qvacua) * Exclude CocoaPods dependencies and Swift builds ([#43], props @slashmo) +* Exclude Bundler, Cargo, and Dart dependencies ([#56]) * Define a [Travis CI pipeline for Asimov](https://travis-ci.com/github/stevegrunwell/asimov) ([#20]) * Add an automated test suite using PHPUnit ([#31]) @@ -74,3 +75,4 @@ Initial public release. [#43]: https://github.com/stevegrunwell/asimov/pull/43 [#52]: https://github.com/stevegrunwell/asimov/pull/52 [#55]: https://github.com/stevegrunwell/asimov/pull/55 +[#56]: https://github.com/stevegrunwell/asimov/pull/56 From 7771aba41ef769bc739c27c75bac6e3d6fffb29b Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 16 Jun 2020 15:58:01 -0400 Subject: [PATCH 63/65] Rewrite the README file now that Asimov is generally available via Homebrew --- README.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 50f1e36..5b07b2b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Asimov [![Build Status](https://travis-ci.com/stevegrunwell/asimov.svg?branch=develop)](https://travis-ci.com/stevegrunwell/asimov) +![Requires macOS 10.13 (High Sierra) or newer](https://img.shields.io/badge/macOS-10.13%20or%20higher-blue) +[![MIT license](https://img.shields.io/badge/license-MIT-green)](LICENSE.txt) > Those people who think they know everything are a great annoyance to those of us who do.
— Issac Asimov @@ -10,25 +12,40 @@ For the average consumer, Time Machine is an excellent choice, especially consid Asimov aims to solve that problem, scanning your filesystem for known dependency directories (e.g. `node_modules/` living adjacent to a `package.json` file) and excluding them from Time Machine backups. After all, why eat up space on your backup drive for something you could easily restore via `npm install`? -## Installation (Homebrew) -First make sure you have [Homebrew](https://brew.sh/) installed, then run: +## Installation + +Asimov may be installed in a few different ways: + +### Installation via Homebrew + +The easiest way to install Asimov is through [Homebrew](https://brew.sh): + +```sh +$ brew install asimov +``` + +If you would prefer to use the latest development release, you may append the `--head` flag: + ```sh -brew install https://raw.githubusercontent.com/stevegrunwell/asimov/develop/Formula/asimov.rb +$ brew install asimov --head ``` -After the installation has finished, you can enable automatic startup and scheduling: +Once installed, you may instruct Homebrew to automatically load the scheduled job, ensuring Asimov is being run automatically every day: + ```sh -sudo brew services start asimov +$ sudo brew services start asimov ``` -or run manually: + +If you don't need or want the scheduled job, you may run Asimov on-demand: + ```sh -asimov +$ asimov ``` -## Installation (Manual) +### Manual installation -To get started with Asimov, clone the repository or download and extract an archive anywhere you'd like on your Mac: +If you would prefer to install Asimov manually, you can do so by cloning the repository (or downloading and extracting an archive of the source) anywhere on your Mac: ```sh $ git clone https://github.com/stevegrunwell/asimov.git --depth 1 @@ -39,6 +56,7 @@ After you've cloned the repository, run the `install.sh` script to automatically * Schedule Asimov to run once a day, ensuring new projects' dependencies are quickly excluded from Time Machine backups. * Run Asimov for the first time, finding all current project dependencies adding them to Time Machine's exclusion list. + ## How it works At its essence, Asimov is a simple wrapper around Apple's `tmutil` program, which provides more granular control over Time Machine. From 0c8129e8adc2ac1b177b55cb90f287dc78ebeb99 Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 16 Jun 2020 16:12:47 -0400 Subject: [PATCH 64/65] Version bump for v0.3.0 --- CHANGELOG.md | 3 ++- asimov | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1349d47..445dfe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased] +## [Version 0.3.0] — 2020-06-16 ### Added @@ -56,6 +56,7 @@ Initial public release. [Unreleased]: https://github.com/stevegrunwell/asimov/compare/master...develop [Version 0.1.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.1.0 [Version 0.2.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.2.0 +[Version 0.3.0]: https://github.com/stevegrunwell/asimov/releases/tag/v0.3.0 [#5]: https://github.com/stevegrunwell/asimov/issues/5 [#7]: https://github.com/stevegrunwell/asimov/issues/7 [#10]: https://github.com/stevegrunwell/asimov/issues/10 diff --git a/asimov b/asimov index 03b5295..9a05768 100755 --- a/asimov +++ b/asimov @@ -13,7 +13,7 @@ set -Eeu -o pipefail # # For a full explanation, please see https://apple.stackexchange.com/a/25833/206772 # -# @version 0.2.0 +# @version 0.3.0 # @author Steve Grunwell # @license MIT From 730c6fcb6c85aebd001b79186bfb2d31630dca8e Mon Sep 17 00:00:00 2001 From: Steve Grunwell Date: Tue, 16 Jun 2020 16:16:31 -0400 Subject: [PATCH 65/65] Remove the Homebrew formula, as that's maintained in https://github.com/Homebrew/homebrew-core/blob/master/Formula/asimov.rb --- Formula/asimov.rb | 53 ----------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 Formula/asimov.rb diff --git a/Formula/asimov.rb b/Formula/asimov.rb deleted file mode 100644 index 8894caa..0000000 --- a/Formula/asimov.rb +++ /dev/null @@ -1,53 +0,0 @@ -class Asimov < Formula - desc "Automatically exclude development dependencies from Time Machine backups" - homepage "https://github.com/stevegrunwell/asimov" - url "https://github.com/stevegrunwell/asimov/archive/v0.2.0.tar.gz" - sha256 "2efb456975af066a17f928787062522de06c14eb322b2d133a8bc3a764cc5376" - revision 0 - - # Setup HEAD support (install with --HEAD) - head "https://github.com/stevegrunwell/asimov.git", :branch => "develop" - - # No bottling necessary - bottle :unneeded - - # Define the installation steps - def install - # Install the application - bin.install buildpath/"asimov" - end - - # Define launch agent plist options (launch automatically, but also allow manual startup) - plist_options :startup => true, :manual => "asimov" - - # Define the agent plist contents - def plist - <<~EOS - - - - - Label - #{plist_name} - Program - #{opt_bin}/asimov - StartInterval - - 86400 - - - EOS - end - - # Define tests to run - test do - # Test that the binary exists - assert File.file?(bin/"asimov"), "asimov binary not found" - - # Test that the symlink exists - assert File.file?("/usr/local/bin/asimov"), "asimov binary symlink not found in /usr/local/bin" - - # Test that the launch agent plist exists - assert File.file?(plist_path), "asimov plist not found in "+plist_path - end -end