├── .codeclimate.yml
├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── CHANGELOG.md
├── CNAME
├── LICENSE.md
├── README.md
├── composer.json
├── env-diff
├── phpunit.xml.dist
├── src
├── Composer
│ └── ScriptHandler.php
├── Config.php
├── Console
│ ├── Application.php
│ └── Command
│ │ ├── AbstractCommand.php
│ │ ├── ActualizeCommand.php
│ │ └── DiffCommand.php
├── Env.php
├── Env
│ ├── Dumper.php
│ └── Parser.php
├── IO
│ ├── ComposerIO.php
│ ├── ConsoleIO.php
│ └── IOInterface.php
└── Processor.php
└── tests
├── Composer
└── ScriptHandlerTest.php
├── ConfigTest.php
├── Console
├── ApplicationTest.php
└── Command
│ └── CommandsTest.php
├── ProcessorTest.php
└── fixtures
├── actualize
├── delete-old-variable
│ ├── .env
│ ├── .env.dist
│ └── .expected
├── invalid
│ ├── dist-not-found
│ │ └── error.txt
│ ├── invalid-delimiter
│ │ ├── .env.dist
│ │ └── error.txt
│ └── invalid-string
│ │ ├── .env.dist
│ │ └── error.txt
├── subdirectory
│ ├── .expected
│ └── sub
│ │ └── .env.dist
└── valid
│ ├── append-new-variable
│ ├── .env
│ ├── .env.dist
│ └── .expected
│ ├── create-new-env-file
│ ├── .env.dist
│ └── .expected
│ ├── do-not-delete-old-variable
│ ├── .env
│ ├── .env.dist
│ └── .expected
│ ├── do-not-replace-old-variable
│ ├── .env
│ ├── .env.dist
│ └── .expected
│ ├── remove-comments
│ ├── .env
│ ├── .env.dist
│ └── .expected
│ └── trim-spaces
│ ├── .env
│ ├── .env.dist
│ └── .expected
└── difference
├── invalid
├── dist-not-found
│ └── error.txt
├── invalid-delimiter
│ ├── .env.dist
│ └── error.txt
├── invalid-string
│ ├── .env.dist
│ └── error.txt
└── target-not-found
│ ├── .env.dist
│ └── error.txt
└── valid
├── changed-values
├── .env
├── .env.dist
└── expected.log
├── extra-values
├── .env
├── .env.dist
└── expected.log
├── identical
├── .env
├── .env.dist
└── expected.log
├── missed-values
├── .env
├── .env.dist
└── expected.log
└── mixed
├── .env
├── .env.dist
└── expected.log
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | duplication:
3 | enabled: true
4 | config:
5 | languages:
6 | - php
7 | fixme:
8 | enabled: true
9 | phpcodesniffer:
10 | enabled: true
11 | phan:
12 | enabled: true
13 | config:
14 | file_extensions: "php"
15 | ignore-undeclared: true
16 | dead-code-detection: true
17 | backward-compatibility-checks: true
18 | checks:
19 | PhanParamTooMany:
20 | enabled: false
21 | phpmd:
22 | enabled: true
23 | checks:
24 | CleanCode/StaticAccess:
25 | enabled: false
26 | Naming/ShortVariable:
27 | enabled: false
28 | ratings:
29 | paths:
30 | - "**.php"
31 |
32 | exclude_paths:
33 | - tests/
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | phpunit.xml
3 | vendor
4 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | filter:
2 | excluded_paths: [tests/*, vendor]
3 |
4 | checks:
5 | php:
6 | code_rating: true
7 | remove_extra_empty_lines: true
8 | remove_php_closing_tag: true
9 | remove_trailing_whitespace: true
10 | fix_use_statements:
11 | remove_unused: true
12 | preserve_multiple: false
13 | preserve_blanklines: true
14 | order_alphabetically: true
15 | fix_php_opening_tag: true
16 | fix_linefeed: true
17 | fix_line_ending: true
18 | fix_identation_4spaces: true
19 | fix_doc_comments: true
20 |
21 | tools:
22 | php_analyzer: true
23 | php_code_sniffer:
24 | config:
25 | standard: PSR2
26 | filter:
27 | paths: ['src']
28 | php_loc:
29 | enabled: true
30 | excluded_dirs: [vendor, tests]
31 | php_cpd:
32 | enabled: true
33 | excluded_dirs: [vendor, tests]
34 |
35 | build:
36 | tests:
37 | override:
38 | -
39 | command: 'vendor/bin/phpunit --coverage-clover=some-file'
40 | coverage:
41 | file: 'some-file'
42 | format: 'clover'
43 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | dist: trusty
4 |
5 | cache:
6 | directories:
7 | - $HOME/.composer/cache/files
8 |
9 | php:
10 | - 5.6
11 | - 7.0
12 | - 7.1
13 | - hhvm
14 |
15 | before_script:
16 | - composer install
17 |
18 | script:
19 | - vendor/bin/phpunit --coverage-clover=phpunit.coverage.xml --log-junit=phpunit.report.xml
20 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 1.0.0 (2017-05-14)
2 |
3 | * Initial release of the library.
4 |
5 | # 1.0.1 (2017-06-01)
6 |
7 | * Update README.md
8 | * Fix travis.yml
9 | * Fix bug in ComposerIO
10 | * Update output messages
11 |
12 | # 1.0.2 (2017-06-05)
13 |
14 | * Remove comments from destination file
15 | * Improve console output messages
16 | * Set "actualize" command as default.
17 |
18 | # 1.0.3 (2017-08-31)
19 |
20 | * Fix config key mismatch
21 | * Update Readme.md
22 |
23 | # 1.1.0 (2018-04-20)
24 |
25 | * Add Symfony 4 support (@craigruks)
26 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | design.magnit.ru
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Lexey Felde
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EnvDiff
2 |
3 | [![Latest Version on Packagist][ico-version]][link-packagist]
4 | [![Software License][ico-license]](LICENSE.md)
5 | [![Build Status][ico-travis]][link-travis]
6 | [![Coverage Status][ico-scrutinizer]][link-scrutinizer]
7 | [![Quality Score][ico-code-quality]][link-code-quality]
8 |
9 | EnvDiff is tool to compare environment keys to find the difference between .env files and actualize them.
10 |
11 | 
12 |
13 | # Installation
14 |
15 | ```
16 | composer require tekill/env-diff
17 | ```
18 |
19 | ## Manual running
20 | ### Actualize variables
21 | Compare `.env` with `.env.dist` and add missing variables to `.env` file.
22 | ```
23 | php ./vendor/bin/env-diff actualize
24 | ```
25 |
26 | Compare `.env` with `.env.example` and add missing variables to `.env` file.
27 | ```
28 | php ./vendor/bin/env-diff actualize .env.example
29 | ```
30 |
31 | Compare `.env-target` with `.env.example` and add missing variables to `.env-target` file.
32 | ```
33 | php ./vendor/bin/env-diff actualize .env.example .env-target
34 | ```
35 |
36 | If you want to delete outdated values just run command with `-k=false` option.
37 |
38 | ```
39 | php ./vendor/bin/env-diff actualize -k=false
40 | ```
41 |
42 | ### Show differences
43 | Command has same interface, arguments and options.
44 |
45 | Compare `.env` with `.env.dist` and show differences between them.
46 | ```
47 | php ./vendor/bin/env-diff diff
48 | ```
49 |
50 | ## Composer script
51 |
52 | Add code block in `composer.json`:
53 | ```$json
54 | "scripts": {
55 | "post-update-cmd": "LF\\EnvDiff\\Composer\\ScriptHandler::actualizeEnv"
56 | }
57 | ```
58 |
59 | The `.env` will then be created or updated by the composer script, to match the structure of the dist
60 | file `.env.dist` by asking you the missing variables.
61 |
62 | By default, the dist file is assumed to be in the same place than the target `.env`
63 | file, suffixed by `.dist`. This can be changed in the configuration:
64 |
65 | ```json
66 | {
67 | "extra": {
68 | "lf-env-diff": [
69 | {
70 | "dist": "path/to/env.dist",
71 | "target": "path/to/.env"
72 | }
73 | ]
74 | }
75 | }
76 | ```
77 |
78 | The script handler will ask you interactively for variables which are missing
79 | in the target env file, using the value of the dist file as default value.
80 | If composer is run in a non-interactive mode `--no-interaction`, the values of the dist file
81 | will be used for missing variables.
82 |
83 | **Warning:** This handler will overwrite any comments or spaces into your target `.env` file so handle with care.
84 |
85 | ### Managing multiple ignored files
86 |
87 | The handler can manage multiple ignored files. To use this feature, the `lf-env-diff` extra should contain a
88 | JSON array with multiple configurations inside it instead of a configuration object:
89 |
90 | ```json
91 | {
92 | "extra": {
93 | "lf-env-diff": [
94 | {
95 | "dist": "path/to/.env.dist",
96 | "target": "path/to/.env"
97 | },
98 | {
99 | "dist": "path/to/.env.dist",
100 | "target": "path/to/.env-test",
101 | "keep-outdated": false
102 | }
103 | ]
104 | }
105 | }
106 | ```
107 |
108 | ### Show difference
109 |
110 | Add code block in `composer.json`:
111 | ```$json
112 | "scripts": {
113 | "post-update-cmd": "LF\\EnvDiff\\Composer\\ScriptHandler::showDifference"
114 | }
115 | ```
116 |
117 | This handler has same behavior as described before.
118 |
119 | ## Git hooks
120 |
121 | You can use Git hook that gets triggered after any 'git pull' whenever one of the files specified has changed.
122 | Useful to update any web application dependency or sync configuration.
123 |
124 | Create `post-merge` hook in `.git/hooks` directory of your project:
125 | ```
126 | #/usr/bin/env bash
127 |
128 | changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
129 |
130 | check_run() {
131 | echo "$changed_files" | grep -E --quiet "$1" && eval "$2"
132 | }
133 |
134 | # Actualize env files if the `env.dist` file gets changed
135 | check_run env.dist "php ./vendor/bin/env-diff actualize"
136 | ```
137 |
138 | [ico-version]: https://img.shields.io/packagist/v/Tekill/env-diff.svg?style=flat-square
139 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
140 | [ico-travis]: https://img.shields.io/travis/Tekill/env-diff/master.svg?style=flat-square
141 | [ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/Tekill/env-diff.svg?style=flat-square
142 | [ico-code-quality]: https://img.shields.io/scrutinizer/g/Tekill/env-diff.svg?style=flat-square
143 |
144 | [link-packagist]: https://packagist.org/packages/Tekill/env-diff
145 | [link-travis]: https://travis-ci.org/Tekill/env-diff
146 | [link-scrutinizer]: https://scrutinizer-ci.com/g/Tekill/env-diff/code-structure/
147 | [link-code-quality]: https://scrutinizer-ci.com/g/Tekill/env-diff
148 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tekill/env-diff",
3 | "description": "Check the difference between env files and actualize each other",
4 | "type": "library",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Lexey Felde",
9 | "email": "felde.lexey@gmail.com"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.6",
14 | "symfony/console": "~2.8|~3.0|~4.0"
15 | },
16 | "require-dev": {
17 | "composer/composer": "1.0.*@dev",
18 | "phpunit/phpunit": "^5.0"
19 | },
20 | "autoload": {
21 | "psr-4": { "LF\\EnvDiff\\": "src/" }
22 | },
23 | "bin": [
24 | "env-diff"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/env-diff:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | run();
19 | }
20 | }
21 |
22 | fwrite(
23 | STDERR,
24 | 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
25 | ' composer install' . PHP_EOL . PHP_EOL .
26 | 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
27 | );
28 |
29 | exit(1);
30 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ./tests/
7 |
8 |
9 |
10 |
11 |
12 | ./src
13 |
14 | ./tests
15 | ./vendor
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Composer/ScriptHandler.php:
--------------------------------------------------------------------------------
1 | getIO()));
26 |
27 | foreach ($configs as $config) {
28 | $processor->actualizeEnv(Config::createFormArray($config));
29 | }
30 | }
31 |
32 | /**
33 | * @param Event $event
34 | *
35 | * @throws InvalidArgumentException
36 | * @throws RuntimeException
37 | */
38 | public static function showDifference(Event $event)
39 | {
40 | $configs = self::extractConfigs($event);
41 | $processor = new Processor(new ComposerIO($event->getIO()));
42 |
43 | foreach ($configs as $config) {
44 | $processor->showDifference(Config::createFormArray($config));
45 | }
46 | }
47 |
48 | /**
49 | * @param Event $event
50 | *
51 | * @return array
52 | *
53 | * @throws InvalidArgumentException
54 | */
55 | private static function extractConfigs(Event $event)
56 | {
57 | $extras = $event->getComposer()->getPackage()->getExtra();
58 |
59 | $configs = isset($extras[self::CONFIG_KEY]) ? $extras[self::CONFIG_KEY] : [[]];
60 |
61 | if (!is_array($configs)) {
62 | throw new InvalidArgumentException(
63 | 'The extra.lf-env-diff setting must be an array or a configuration object'
64 | );
65 | }
66 |
67 | foreach ($configs as $config) {
68 | if (!is_array($config)) {
69 | throw new InvalidArgumentException(
70 | 'The extra.lf-env-diff setting must be an array of configuration objects'
71 | );
72 | }
73 | }
74 |
75 | return $configs;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Config.php:
--------------------------------------------------------------------------------
1 | dist = $dist;
29 | $this->target = $target;
30 | $this->keepOutdatedEnv = $keepOutdatedEnv;
31 | }
32 |
33 | /**
34 | * @param array $config
35 | *
36 | * @return static
37 | */
38 | public static function createFormArray(array $config = [])
39 | {
40 | if (empty($config['target'])) {
41 | $config['target'] = '.env';
42 | }
43 | if (empty($config['dist'])) {
44 | $config['dist'] = $config['target'] . '.dist';
45 | }
46 | if (!isset($config['keep-outdated'])) {
47 | $config['keep-outdated'] = true;
48 | }
49 |
50 | return new static($config['dist'], $config['target'], (bool) $config['keep-outdated']);
51 | }
52 |
53 | /**
54 | * @return string
55 | */
56 | public function getDist()
57 | {
58 | return $this->dist;
59 | }
60 |
61 | /**
62 | * @return string
63 | */
64 | public function getTarget()
65 | {
66 | return $this->target;
67 | }
68 |
69 | /**
70 | * @return boolean
71 | */
72 | public function isKeepOutdatedEnv()
73 | {
74 | return $this->keepOutdatedEnv;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Console/Application.php:
--------------------------------------------------------------------------------
1 | setAutoExit(true);
22 | $this->add(new DiffCommand('diff'));
23 | $this->add(new ActualizeCommand('actualize'));
24 |
25 | $this->setDefaultCommand('actualize');
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Console/Command/AbstractCommand.php:
--------------------------------------------------------------------------------
1 | addArgument('dist', InputOption::VALUE_REQUIRED, 'From file', Config::DEFAULT_DIST)
23 | ->addArgument('target', InputOption::VALUE_REQUIRED, 'To file', Config::DEFAULT_TARGET)
24 | ->addOption('keep-outdated', 'k', InputOption::VALUE_OPTIONAL, 'Keep old env variables', true);
25 | }
26 |
27 | /**
28 | * {@inheritdoc}
29 | *
30 | * @throws InvalidArgumentException
31 | */
32 | protected function execute(InputInterface $input, OutputInterface $output)
33 | {
34 | $config = $this->createConfig($input);
35 | $processor = $this->createProcessor($input, $output);
36 |
37 | $this->doExecute($processor, $config);
38 |
39 | return 0;
40 | }
41 |
42 | /**
43 | * @param InputInterface $input
44 | *
45 | * @return Config
46 | *
47 | * @throws InvalidArgumentException
48 | */
49 | private function createConfig(InputInterface $input)
50 | {
51 | $dist = $input->getArgument('dist');
52 | $target = $input->getArgument('target');
53 | $keepOutdated = $input->getOption('keep-outdated');
54 |
55 | return new Config($dist, $target, $keepOutdated);
56 | }
57 |
58 | /**
59 | * @param InputInterface $input
60 | * @param OutputInterface $output
61 | *
62 | * @return Processor
63 | */
64 | private function createProcessor(InputInterface $input, OutputInterface $output)
65 | {
66 | return new Processor(new ConsoleIO($input, $output));
67 | }
68 |
69 | /**
70 | * @param Processor $processor
71 | * @param Config $config
72 | */
73 | abstract protected function doExecute(Processor $processor, Config $config);
74 | }
75 |
--------------------------------------------------------------------------------
/src/Console/Command/ActualizeCommand.php:
--------------------------------------------------------------------------------
1 | actualizeEnv($config);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Console/Command/DiffCommand.php:
--------------------------------------------------------------------------------
1 | showDifference($config);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Env.php:
--------------------------------------------------------------------------------
1 | dump($envArray);
19 | }
20 |
21 | /**
22 | * @param string $path
23 | *
24 | * @return array
25 | *
26 | * @throws InvalidArgumentException
27 | */
28 | public static function parse($path)
29 | {
30 | return (new Parser())->parse($path);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Env/Dumper.php:
--------------------------------------------------------------------------------
1 | $variable) {
17 | $dump .= sprintf('%s=%s%s', $env, $variable, PHP_EOL);
18 | }
19 |
20 | return trim($dump);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Env/Parser.php:
--------------------------------------------------------------------------------
1 | isCommentOrEmpty($line)) {
31 | continue;
32 | }
33 | if (false === strpos($line, '=')) {
34 | throw new InvalidArgumentException(
35 | sprintf('Parse error at %d line: `%s` is not valid env value', $number, $line)
36 | );
37 | }
38 |
39 | list($name, $value) = explode('=', $line, 2);
40 | $env[trim($name)] = trim($value);
41 | }
42 |
43 | fclose($file);
44 |
45 | return $env;
46 | }
47 |
48 | /**
49 | * @param string $line
50 | *
51 | * @return bool
52 | */
53 | private function isCommentOrEmpty($line)
54 | {
55 | return (mb_strlen($line) === 0 || $line[0] === '#');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/IO/ComposerIO.php:
--------------------------------------------------------------------------------
1 | io = $io;
23 | }
24 |
25 | /**
26 | * @param string $message
27 | */
28 | public function write($message)
29 | {
30 | $this->io->write($message);
31 | }
32 |
33 | /**
34 | * @return bool
35 | */
36 | public function isInteractive()
37 | {
38 | return $this->io->isInteractive();
39 | }
40 |
41 | /**
42 | * @param string $question
43 | * @param string|null $default
44 | *
45 | * @return string
46 | *
47 | * @throws \RuntimeException
48 | */
49 | public function ask($question, $default = null)
50 | {
51 | return $this->io->ask($question, $default);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/IO/ConsoleIO.php:
--------------------------------------------------------------------------------
1 | input = $input;
33 | $this->output = $output;
34 | $this->questionHelper = new QuestionHelper();
35 | }
36 |
37 | /**
38 | * @param string $message
39 | */
40 | public function write($message)
41 | {
42 | $this->output->writeln($message);
43 | }
44 |
45 | /**
46 | * @return bool
47 | */
48 | public function isInteractive()
49 | {
50 | return $this->input->isInteractive();
51 | }
52 |
53 | /**
54 | * @param string $question
55 | * @param string|null $default
56 | *
57 | * @return string
58 | *
59 | * @throws \RuntimeException
60 | */
61 | public function ask($question, $default = null)
62 | {
63 | return $this->questionHelper->ask($this->input, $this->output, new Question($question, $default));
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/IO/IOInterface.php:
--------------------------------------------------------------------------------
1 | io = $io;
22 | }
23 |
24 | /**
25 | * @param Config $config
26 | *
27 | * @throws InvalidArgumentException
28 | * @throws RuntimeException
29 | *
30 | * @return bool
31 | */
32 | public function actualizeEnv(Config $config)
33 | {
34 | $dist = $config->getDist();
35 | $target = $config->getTarget();
36 | $exists = is_file($target);
37 |
38 | $this->io->write(sprintf('Actualize env from "%s">', $dist));
39 |
40 | try {
41 | $distEnv = Env::parse($dist);
42 | $actualEnv = $exists ? Env::parse($target) : [];
43 | } catch (InvalidArgumentException $exception) {
44 | $this->io->write(sprintf('%s, abort', $exception->getMessage()));
45 |
46 | return true;
47 | }
48 |
49 | $actualEnv = $this->processEnv($distEnv, $actualEnv, $config->isKeepOutdatedEnv());
50 |
51 | if (!is_dir($dir = dirname($target))) {
52 | mkdir($dir, 0755, true);
53 | }
54 |
55 | ksort($actualEnv);
56 | file_put_contents($target, Env::dump($actualEnv));
57 |
58 | $this->io->write(sprintf('"%s" has been %s', $target, $exists ? 'updated' : 'created'));
59 |
60 | return false;
61 | }
62 |
63 | /**
64 | * @param Config $config
65 | *
66 | * @throws InvalidArgumentException
67 | *
68 | * @return bool
69 | */
70 | public function showDifference(Config $config)
71 | {
72 | $dist = $config->getDist();
73 | $target = $config->getTarget();
74 |
75 | try {
76 | $distEnv = Env::parse($dist);
77 | $actualEnv = Env::parse($target);
78 | } catch (InvalidArgumentException $exception) {
79 | $this->io->write(sprintf('%s', $exception->getMessage()));
80 |
81 | return true;
82 | }
83 |
84 | $extraEnv = array_diff_key($actualEnv, $distEnv);
85 | $missingEnv = array_diff_key($distEnv, $actualEnv);
86 | $changedEnv = array_diff(array_intersect_key($distEnv, $actualEnv), $actualEnv);
87 |
88 | if (!count($missingEnv) && !count($extraEnv) && !count($changedEnv)) {
89 | $this->io->write(sprintf('"%s" and "%s" is identical', $target, $dist));
90 |
91 | return false;
92 | }
93 |
94 | $this->io->write(sprintf('Diff between "%s" and "%s" files:', $target, $dist));
95 | $this->io->write('');
96 |
97 | foreach ($missingEnv as $env => $value) {
98 | $this->io->write(sprintf('- %s=%s>', $env, $value));
99 | }
100 | foreach ($extraEnv as $env => $value) {
101 | $this->io->write(sprintf('+ %s=%s>', $env, $value));
102 | }
103 | foreach ($changedEnv as $env => $default) {
104 | $this->io->write(sprintf('@ %s=%s (%s)>', $env, $actualEnv[$env], $default));
105 | }
106 |
107 | return false;
108 | }
109 |
110 | /**
111 | * @param array $expectedEnv
112 | * @param array $actualEnv
113 | * @param bool $keepOutdated
114 | *
115 | * @return array
116 | *
117 | * @throws RuntimeException
118 | */
119 | private function processEnv(array $expectedEnv, array $actualEnv, $keepOutdated)
120 | {
121 | if (false === $keepOutdated) {
122 | $actualEnv = array_intersect_key($actualEnv, $expectedEnv);
123 | }
124 |
125 | return $this->getEnv($expectedEnv, $actualEnv);
126 | }
127 |
128 | /**
129 | * @param array $expectedEnv
130 | * @param array $actualEnv
131 | *
132 | * @return array
133 | *
134 | * @throws RuntimeException
135 | */
136 | private function getEnv(array $expectedEnv, array $actualEnv)
137 | {
138 | if (!$this->io->isInteractive()) {
139 | return array_replace($expectedEnv, $actualEnv);
140 | }
141 |
142 | $diffEnv = array_diff_key($expectedEnv, $actualEnv);
143 | if (count($diffEnv) > 0) {
144 | $this->io->write('Some env variables are missing. Please provide them.');
145 |
146 | foreach ($diffEnv as $env => $default) {
147 | $actualEnv[$env] = $this->io->ask(
148 | sprintf('%s (%s): ', $env, $default),
149 | $default
150 | );
151 | }
152 | }
153 |
154 | return $actualEnv;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/tests/Composer/ScriptHandlerTest.php:
--------------------------------------------------------------------------------
1 | [
23 | ['lf-env-diff' => 'not an array'],
24 | 'The extra.lf-env-diff setting must be an array or a configuration object',
25 | ],
26 | 'invalid type for multiple configs' => [
27 | ['lf-env-diff' => ['not an array']],
28 | 'The extra.lf-env-diff setting must be an array of configuration objects',
29 | ],
30 | ];
31 | }
32 |
33 | /**
34 | * @dataProvider provideInvalidConfiguration()
35 | *
36 | * @param array $extras
37 | * @param string $exceptionMessage
38 | */
39 | public function testActualizeEnvInvalidConfiguration(array $extras, $exceptionMessage)
40 | {
41 | $this->expectException(InvalidArgumentException::class);
42 | $this->expectExceptionMessage($exceptionMessage);
43 |
44 | $event = $this->createEvent($extras);
45 | $event
46 | ->expects(self::never())
47 | ->method('getIO');
48 |
49 | ScriptHandler::actualizeEnv($event);
50 | }
51 |
52 | /**
53 | * @dataProvider provideInvalidConfiguration()
54 | *
55 | * @param array $extras
56 | * @param string $exceptionMessage
57 | */
58 | public function testShowDifferenceInvalidConfiguration(array $extras, $exceptionMessage)
59 | {
60 | $this->expectException(InvalidArgumentException::class);
61 | $this->expectExceptionMessage($exceptionMessage);
62 |
63 | $event = $this->createEvent($extras);
64 | $event
65 | ->expects(self::never())
66 | ->method('getIO');
67 |
68 | ScriptHandler::showDifference($event);
69 | }
70 |
71 | /**
72 | * @return array
73 | */
74 | public function provideValidConfiguration()
75 | {
76 | return [
77 | [
78 | [
79 | 'lf-env-diff' => [
80 | [
81 | 'dist' => 'fixtures/difference/valid/identical/.env.dist',
82 | 'target' => 'fixtures/difference/valid/identical/.env'
83 | ],
84 | [
85 | 'dist' => 'fixtures/difference/valid/identical/.env.dist',
86 | 'target' => 'fixtures/difference/valid/identical/.env'
87 | ]
88 | ]
89 | ]
90 | ]
91 | ];
92 | }
93 |
94 | /**
95 | * @dataProvider provideValidConfiguration()
96 | *
97 | * @param array $extras
98 | */
99 | public function testActualizeEnvValidConfiguration(array $extras)
100 | {
101 | $io = $this->createMock(IOInterface::class);
102 |
103 | $event = $this->createEvent($extras);
104 | $event
105 | ->expects(self::once())
106 | ->method('getIO')
107 | ->willReturn($io);
108 |
109 | chdir(dirname(__DIR__));
110 | ScriptHandler::actualizeEnv($event);
111 | }
112 |
113 | /**
114 | * @dataProvider provideValidConfiguration()
115 | *
116 | * @param array $extras
117 | */
118 | public function testShowDifferenceValidConfiguration(array $extras)
119 | {
120 | $io = $this->createMock(IOInterface::class);
121 |
122 | $event = $this->createEvent($extras);
123 | $event
124 | ->expects(self::once())
125 | ->method('getIO')
126 | ->willReturn($io);
127 |
128 | chdir(dirname(__DIR__));
129 | ScriptHandler::showDifference($event);
130 | }
131 |
132 | /**
133 | * @param array $extras
134 | *
135 | * @return PHPUnit_Framework_MockObject_MockObject | Event
136 | */
137 | private function createEvent(array $extras = [])
138 | {
139 | $package = $this->createMock(PackageInterface::class);
140 | $package->expects(self::once())
141 | ->method('getExtra')
142 | ->willReturn($extras);
143 |
144 | $composer = $this->createMock(Composer::class);
145 | $composer->expects(self::once())
146 | ->method('getPackage')
147 | ->willReturn($package);
148 |
149 | $event = $this->createMock(Event::class);
150 | $event->expects(self::once())
151 | ->method('getComposer')
152 | ->willReturn($composer);
153 |
154 | return $event;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/tests/ConfigTest.php:
--------------------------------------------------------------------------------
1 | [
17 | [],
18 | new Config('.env.dist', '.env')
19 | ],
20 | 'custom target' => [
21 | ['target' => '.custom'],
22 | new Config('.custom.dist', '.custom')
23 | ],
24 | 'custom target & dist' => [
25 | ['target' => '.custom', 'dist' => '.env.dist'],
26 | new Config('.env.dist', '.custom')
27 | ],
28 | 'keep-outdated is false' => [
29 | ['keep-outdated' => false],
30 | new Config('.env.dist', '.env', false)
31 | ]
32 | ];
33 | }
34 |
35 | /**
36 | * @dataProvider createFromArrayDataProvider()
37 | *
38 | * @param array $array
39 | * @param Config $expected
40 | */
41 | public function testCreateFromArray(array $array, Config $expected)
42 | {
43 | self::assertEquals($expected, Config::createFormArray($array));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/Console/ApplicationTest.php:
--------------------------------------------------------------------------------
1 | has('diff'));
15 | self::assertTrue($application->has('actualize'));
16 | self::assertTrue($application->isAutoExitEnabled());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Console/Command/CommandsTest.php:
--------------------------------------------------------------------------------
1 | [new DiffCommand('name')],
21 | 'actualize' => [new ActualizeCommand('name')],
22 | ];
23 | }
24 |
25 | /**
26 | * @dataProvider dataRun()
27 | *
28 | * @param Command $command
29 | */
30 | public function testRun(Command $command)
31 | {
32 | $input = $this
33 | ->getMockBuilder(Input::class)
34 | ->disableOriginalConstructor()
35 | ->getMock();
36 | $output = $this
37 | ->getMockBuilder(Output::class)
38 | ->disableOriginalConstructor()
39 | ->setMethods(['write', 'doWrite'])
40 | ->getMock();
41 | $output->expects(self::atLeastOnce())
42 | ->method('write');
43 |
44 | self::assertEquals(
45 | 0,
46 | $command->run($input, $output)
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/ProcessorTest.php:
--------------------------------------------------------------------------------
1 | io = $this->createMock(IOInterface::class);
24 | $this->processor = new Processor($this->io);
25 | }
26 |
27 | /**
28 | * @return array
29 | */
30 | public function actualizeEnvDataProvider()
31 | {
32 | $config = Config::createFormArray(
33 | [
34 | 'dist' => '.env.dist',
35 | 'target' => '.env'
36 | ]
37 | );
38 | $tests = [];
39 |
40 | foreach (glob(__DIR__ . '/fixtures/actualize/valid/*/') as $folder) {
41 | $tests[basename($folder)] = [$folder, $config, false];
42 | $tests[basename($folder) . ' interactive'] = [$folder, $config, true];
43 | }
44 |
45 | $subdirectory = realpath(__DIR__ . '/fixtures/actualize/subdirectory/') . '/';
46 | $configSubdirectory = Config::createFormArray(
47 | [
48 | 'dist' => 'sub/.env.dist',
49 | 'target' => 'expected/.env'
50 | ]
51 | );
52 |
53 | $tests[$subdirectory] = [$subdirectory, $configSubdirectory, false];
54 | $tests[$subdirectory . ' interactive'] = [$subdirectory, $configSubdirectory, false];
55 |
56 | return $tests;
57 | }
58 |
59 | /**
60 | * @dataProvider actualizeEnvDataProvider()
61 | *
62 | * @param string $directory
63 | * @param Config $config
64 | * @param bool $isInteractive
65 | */
66 | public function testActualizeEnv($directory, Config $config, $isInteractive)
67 | {
68 | $workingDir = sys_get_temp_dir() . '/lf_env_diff_tests/';
69 | $fs = new Filesystem();
70 |
71 | if (is_dir($workingDir)) {
72 | $fs->remove($workingDir);
73 | }
74 |
75 | $fs->copy($directory . $config->getDist(), $workingDir . $config->getDist());
76 |
77 | if ($exists = file_exists($directory . '/' . $config->getTarget())) {
78 | $fs->copy($directory . $config->getTarget(), $workingDir . $config->getTarget());
79 | }
80 |
81 | chdir($workingDir);
82 | $this->io->expects(self::once())
83 | ->method('isInteractive')
84 | ->willReturn($isInteractive);
85 | $this->io->expects(self::any())
86 | ->method('write');
87 | $this->io->expects(self::any())
88 | ->method('ask')
89 | ->willReturnArgument(1);
90 |
91 | self::assertFalse(
92 | $this->processor->actualizeEnv($config)
93 | );
94 | self::assertFileEquals(
95 | $directory . '/.expected',
96 | $workingDir . $config->getTarget()
97 | );
98 | }
99 |
100 | /**
101 | * @return array
102 | */
103 | public function actualizeEnvDataWithRemoveOutdatedProvider()
104 | {
105 | $tests = [];
106 |
107 | $subdirectory = realpath(__DIR__ . '/fixtures/actualize/delete-old-variable/') . '/';
108 | $configSubdirectory = new Config('.env.dist', '.env', false);
109 |
110 | $tests[$subdirectory] = [$subdirectory, $configSubdirectory, false];
111 | $tests[$subdirectory . ' interactive'] = [$subdirectory, $configSubdirectory, false];
112 |
113 | return $tests;
114 | }
115 |
116 | /**
117 | * @dataProvider actualizeEnvDataWithRemoveOutdatedProvider()
118 | *
119 | * @param string $directory
120 | * @param Config $config
121 | * @param bool $isInteractive
122 | */
123 | public function testActualizeEnvWithRemoveOutdated($directory, Config $config, $isInteractive)
124 | {
125 | $workingDir = sys_get_temp_dir() . '/lf_env_diff_tests/';
126 | $fs = new Filesystem();
127 |
128 | if (is_dir($workingDir)) {
129 | $fs->remove($workingDir);
130 | }
131 |
132 | $fs->copy($directory . $config->getDist(), $workingDir . $config->getDist());
133 |
134 | if ($exists = file_exists($directory . '/' . $config->getTarget())) {
135 | $fs->copy($directory . $config->getTarget(), $workingDir . $config->getTarget());
136 | }
137 |
138 | chdir($workingDir);
139 | $this->io->expects(self::once())
140 | ->method('isInteractive')
141 | ->willReturn($isInteractive);
142 | $this->io->expects(self::any())
143 | ->method('write');
144 | $this->io->expects(self::any())
145 | ->method('ask')
146 | ->willReturnArgument(1);
147 |
148 | self::assertFalse(
149 | $this->processor->actualizeEnv($config)
150 | );
151 | self::assertFileEquals(
152 | $directory . '/.expected',
153 | $workingDir . $config->getTarget()
154 | );
155 | }
156 |
157 | /**
158 | * @return array
159 | */
160 | public function actualizeEnvParseFailedDataProvider()
161 | {
162 | $invalidDirectory = 'fixtures/actualize/invalid/';
163 | $tests = [];
164 |
165 | foreach (scandir(__DIR__ . '/' . $invalidDirectory) as $folder) {
166 | if ($folder === '.' || $folder === '..') {
167 | continue;
168 | }
169 | $tests[basename($folder)] = [
170 | new Config($invalidDirectory . $folder . '/.env.dist'),
171 | file_get_contents(__DIR__ . '/' . $invalidDirectory . $folder . '/error.txt')
172 | ];
173 | }
174 |
175 | return $tests;
176 | }
177 |
178 | /**
179 | * @dataProvider actualizeEnvParseFailedDataProvider()
180 | *
181 | * @param Config $config
182 | * @param string $errorMessage
183 | */
184 | public function testActualizeEnvParseFailed(Config $config, $errorMessage)
185 | {
186 | $this->io->expects(self::at(1))
187 | ->method('write')
188 | ->with($errorMessage);
189 |
190 | chdir(__DIR__);
191 | self::assertTrue(
192 | $this->processor->actualizeEnv($config)
193 | );
194 | }
195 |
196 | /**
197 | * @return array
198 | */
199 | public function showDifferenceDataProvider()
200 | {
201 | $tests = [];
202 |
203 | foreach (glob(__DIR__ . '/fixtures/difference/valid/*/') as $folder) {
204 | $tests[basename($folder)] = [$folder, file($folder . 'expected.log')];
205 | }
206 |
207 | return $tests;
208 | }
209 |
210 | /**
211 | * @dataProvider showDifferenceDataProvider()
212 | *
213 | * @param string $directory
214 | * @param array $lines
215 | */
216 | public function testShowDifference($directory, array $lines)
217 | {
218 | $config = Config::createFormArray(
219 | [
220 | 'dist' => '.env.dist',
221 | 'target' => '.env'
222 | ]
223 | );
224 |
225 | foreach ($lines as $id => $line) {
226 | $this->io->expects(self::at($id))
227 | ->method('write')
228 | ->with(trim($line));
229 | }
230 |
231 | chdir($directory);
232 |
233 | self::assertFalse(
234 | $this->processor->showDifference($config)
235 | );
236 | }
237 |
238 | /**
239 | * @return array
240 | */
241 | public function showDifferenceParseFailedDataProvider()
242 | {
243 | $invalidDirectory = 'fixtures/difference/invalid/';
244 | $tests = [];
245 |
246 | foreach (scandir(__DIR__ . '/' . $invalidDirectory) as $folder) {
247 | if ($folder === '.' || $folder === '..') {
248 | continue;
249 | }
250 | $tests[basename($folder)] = [
251 | new Config($invalidDirectory . $folder . '/.env.dist', $invalidDirectory . $folder . '/.env'),
252 | file_get_contents(__DIR__ . '/' . $invalidDirectory . $folder . '/error.txt')
253 | ];
254 | }
255 |
256 | return $tests;
257 | }
258 |
259 | /**
260 | * @dataProvider showDifferenceParseFailedDataProvider()
261 | *
262 | * @param Config $config
263 | * @param string $errorMessage
264 | */
265 | public function testShowDifferenceFailed(Config $config, $errorMessage)
266 | {
267 | $this->io->expects(self::once())
268 | ->method('write')
269 | ->with($errorMessage);
270 |
271 | chdir(__DIR__);
272 | self::assertTrue(
273 | $this->processor->showDifference($config)
274 | );
275 | }
276 | }
277 |
--------------------------------------------------------------------------------
/tests/fixtures/actualize/delete-old-variable/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | SOME_VARIABLE='old'
3 |
--------------------------------------------------------------------------------
/tests/fixtures/actualize/delete-old-variable/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/delete-old-variable/.expected:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/invalid/dist-not-found/error.txt:
--------------------------------------------------------------------------------
1 | The file "fixtures/actualize/invalid/dist-not-found/.env.dist" does not exist, abort
--------------------------------------------------------------------------------
/tests/fixtures/actualize/invalid/invalid-delimiter/.env.dist:
--------------------------------------------------------------------------------
1 | FOO:'bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/invalid/invalid-delimiter/error.txt:
--------------------------------------------------------------------------------
1 | Parse error at 1 line: `FOO:'bar'` is not valid env value, abort
--------------------------------------------------------------------------------
/tests/fixtures/actualize/invalid/invalid-string/.env.dist:
--------------------------------------------------------------------------------
1 | this is not a valid env variable
--------------------------------------------------------------------------------
/tests/fixtures/actualize/invalid/invalid-string/error.txt:
--------------------------------------------------------------------------------
1 | Parse error at 1 line: `this is not a valid env variable` is not valid env value, abort
--------------------------------------------------------------------------------
/tests/fixtures/actualize/subdirectory/.expected:
--------------------------------------------------------------------------------
1 | APPEND='new line'
2 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/subdirectory/sub/.env.dist:
--------------------------------------------------------------------------------
1 | FOO= 'bar'
2 |
3 | APPEND = 'new line'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/append-new-variable/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/append-new-variable/.env.dist:
--------------------------------------------------------------------------------
1 | # Line with comment
2 | FOO='bar'
3 | APPEND='new line'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/append-new-variable/.expected:
--------------------------------------------------------------------------------
1 | APPEND='new line'
2 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/create-new-env-file/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | NUMBER=123
3 | BOOLEAN=true
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/create-new-env-file/.expected:
--------------------------------------------------------------------------------
1 | BOOLEAN=true
2 | FOO='bar'
3 | NUMBER=123
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-delete-old-variable/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | SOME_VARIABLE='old'
3 |
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-delete-old-variable/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-delete-old-variable/.expected:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | SOME_VARIABLE='old'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-replace-old-variable/.env:
--------------------------------------------------------------------------------
1 | FOO='old'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-replace-old-variable/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/do-not-replace-old-variable/.expected:
--------------------------------------------------------------------------------
1 | FOO='old'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/remove-comments/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/remove-comments/.env.dist:
--------------------------------------------------------------------------------
1 | # Head comment
2 |
3 | FOO= 'bar' #Line comment
4 |
5 | #Another comment
6 | # ENABLED=true
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/remove-comments/.expected:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/trim-spaces/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/trim-spaces/.env.dist:
--------------------------------------------------------------------------------
1 | FOO= 'bar'
2 |
3 | APPEND = 'new line'
--------------------------------------------------------------------------------
/tests/fixtures/actualize/valid/trim-spaces/.expected:
--------------------------------------------------------------------------------
1 | APPEND='new line'
2 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/dist-not-found/error.txt:
--------------------------------------------------------------------------------
1 | The file "fixtures/difference/invalid/dist-not-found/.env.dist" does not exist
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/invalid-delimiter/.env.dist:
--------------------------------------------------------------------------------
1 | FOO:'bar'
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/invalid-delimiter/error.txt:
--------------------------------------------------------------------------------
1 | Parse error at 1 line: `FOO:'bar'` is not valid env value
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/invalid-string/.env.dist:
--------------------------------------------------------------------------------
1 | this is not a valid env variable
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/invalid-string/error.txt:
--------------------------------------------------------------------------------
1 | Parse error at 1 line: `this is not a valid env variable` is not valid env value
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/target-not-found/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/difference/invalid/target-not-found/error.txt:
--------------------------------------------------------------------------------
1 | The file "fixtures/difference/invalid/target-not-found/.env" does not exist
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/changed-values/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new'
3 |
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/changed-values/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/changed-values/expected.log:
--------------------------------------------------------------------------------
1 | Diff between ".env" and ".env.dist" files:
2 |
3 | @ APPEND='new' ('new line')>
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/extra-values/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
3 | EXTRA=true
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/extra-values/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/extra-values/expected.log:
--------------------------------------------------------------------------------
1 | Diff between ".env" and ".env.dist" files:
2 |
3 | + EXTRA=true>
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/identical/.env:
--------------------------------------------------------------------------------
1 | APPEND='new line'
2 | FOO='bar'
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/identical/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/identical/expected.log:
--------------------------------------------------------------------------------
1 | ".env" and ".env.dist" is identical
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/missed-values/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 |
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/missed-values/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/missed-values/expected.log:
--------------------------------------------------------------------------------
1 | Diff between ".env" and ".env.dist" files:
2 |
3 | - APPEND='new line'>
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/mixed/.env:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new'
3 | EXTRA=true
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/mixed/.env.dist:
--------------------------------------------------------------------------------
1 | FOO='bar'
2 | APPEND='new line'
3 | MISSED=true
--------------------------------------------------------------------------------
/tests/fixtures/difference/valid/mixed/expected.log:
--------------------------------------------------------------------------------
1 | Diff between ".env" and ".env.dist" files:
2 |
3 | - MISSED=true>
4 | + EXTRA=true>
5 | @ APPEND='new' ('new line')>
--------------------------------------------------------------------------------