PHPCheckstyle/phpcheckstyle

Run the run.php script from within any directory

MetalArend opened this issue · 20 comments

First of all: big thanks for this awesome tool!

Trying it out however, I have run into a small problem with using relative paths. Running the following line:

php /composer/vendor/phpcheckstyle/phpcheckstyle/run.php --src "./src"

I receive the error

Fatal error: Uncaught Error: Class 'PHPCheckstyle\PHPCheckstyle' not found in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php:172
Stack trace:
#0 {main}
  thrown in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php on line 172

Trying to load the /composer/vendor/autoload.php solves this, but it will still complain about not finding the default config file, as it is defined relatively to the location the script is run from, not relatively to the script itself.

This dependency on the location where php is run from is found on other lines as well:

Is there some way to update run.php to make the script run from anywhere? Or even make it possible to run it as a binary in /composer/vendor/bin (which might take advantage from these same changes)? Honestly, I'm not really sure if these would be the only changes needed to being able to run the above line, as --src "./src" is still using a relative path to the location the script has been called from...

Thanks for looking into this. I would be glad to help to provide further details if needed.

OK, good question.

About the --src, I think you can use absolute paths, its not a problem.

About the classloading, I'll have a look. I personnaly use small shell scripts in my projects to setup the working dir. I think we have a issue opened to provide a command in the /bin dir of composer, but I' havn't taken the time to solve this yet.

Thanks for looking into this.

I have been playing around a bit with the script.

About the --src, I think you can use absolute paths, its not a problem.

Yeah, absolute paths are certainly working, I'm actually using that as some sort of "workaround" for now. But I would want to be able to use relative paths to the directory I'm calling from, not relative to the directory the run.php script is in.

If you try to run

php -r "include '/composer/vendor/autoload.php'; include '/composer/vendor/phpcheckstyle/phpcheckstyle/run.php';" -- --src "./src"

it is still throwing an error on the mentioned files not being found, as it would be able to load phpcheckstyle correctly, but cannot find for example the config file relative to the current working directory. But the current working directory needs to be to keep the relative source path working.

I also tried something like

php -r "chdir('/composer/vendor/phpcheckstyle/phpcheckstyle/'); include 'run.php';" -- --src "./src"

but still no luck.

I think I understand your problem but I havn't been able to reproduce it yet.

About the default config, it should be just a filename and it's relative to the projet path in the
config loader.

On my vagrant box, my default command looks like that :
php run.php --src ./src --outdir ./checkstyle_result --config default.cfg.xml --format html,xml

I've tried to go in the src directory and call it with relative paths :
php ../run.php --src ../src --outdir ../checkstyle_result --config default.cfg.xml --format html,xml
It works too.

I've tried to go up 2 directories :
php ./vagrant/run.php --src ./vagrant/src --outdir ./vagrant/checkstyle_result --format html,xml
And still OK.

But i'm using the composer autoloader.

About the autoload i'm more worried, i know i've changed things several times, I struggle to find a solution that works both with and without composer.

You can try to uncomment line 142 in run.php and comment line 143 to restore the previous way of working (path relative to the installation path of run.php).

I have a project that uses PHPCheckstyle, but I'm using gradle to launch the process and I change the working dir to force it to be correct.

I'll do some more tests ...

Might be It's because I'm trying to do a composer global require, but using it on the local project. I'll try to make a minimal reproducable case.

When you do

php run.php --src ./src

it is running phpcheckstyle on the src directory inside the phpcheckstyle directory.

However, the src I was referring to is the src directory in a symfony project. Sorry for the confusion.

The project I have used to test is a Symfony project too.

My directory looks like this :
/ project / website / app /
/ project / website / bin /
/ project / website / src /
/ project / website / var /
/ project / website / vendor /
/ project / website / vendor / bin /
/ project / website / vendor / composer /
/ project / website / vendor / phpcheckstyle /
/ project / website / vendor ...

And in /project I have a script shell "phpcheckstyle.sh" with this content :

#!/bin/sh
echo "PHP CheckStyle script"
php ./website/vendor/phpcheckstyle/phpcheckstyle/run.php --src ./website/src --outdir ./build/reports/checkstyle_result/ --config default.cfg.xml --format html,xml --exclude Tests --linecount

Ah, I see. I double checked my initial post, and I failed to mention something quite important: I'm installing phpcheckstyle as a global dependency.

I'm using composer global require --dev phpcheckstyle/phpcheckstyle, with COMPOSER_HOME=/composer.

So my directory structure looks like this:
/ project / website / app /
/ project / website / bin /
/ project / website / src /
/ project / website / var /
/ composer / vendor /
/ composer / vendor / bin /
/ composer / vendor / composer /
/ composer / vendor / phpcheckstyle /

Whenever I run a "phpcheckstyle.sh" with the following command (calling for the global phpcheckstyle):

php /composer/vendor/phpcheckstyle/phpcheckstyle/run.php --src ./website/src --outdir ./build/reports/checkstyle_result/ --config default.cfg.xml --format html,xml --exclude Tests --linecount

I get the error:

Fatal error: Uncaught Error: Class 'PHPCheckstyle\PHPCheckstyle' not found in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php:172
Stack trace:
#0 {main}
  thrown in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php on line 172

When I run:

php -r "include '/composer/vendor/autoload.php'; include '/composer/vendor/phpcheckstyle/phpcheckstyle/run.php';" -- --src ./src

It returns this error (including the #!/usr/bin/php line - don't know exactly the best way to avoid that line, but it seems it is not really needed if you call run.php as a script with php):

#!/usr/bin/php
Config file not found : default.cfg.xml

If I run

php -r "chdir('/composer/vendor/phpcheckstyle/phpcheckstyle/'); include 'run.php';" -- --src ./src

it will run on the src directory from phpcheckstyle itself - which actually seems to be logical, but it means chdir is not an option.

I should have mentioned the global requiring earlier, sorry for wasting your time... I hope with this new information, it is reproducable on your machine?

I've done a fast test by moving my /vendor directory to the root of the system. And calling it using your first test worked :
php /composer/vendor/phpcheckstyle/phpcheckstyle/run.php --src ./website/src --outdir ./build/reports/checkstyle_result/ --config default.cfg.xml --format html,xml --exclude Tests --linecount

So it may have to do with the composer autoloader, maybe there is a difference in the autoload.php file itself when installed with the global option. I'll try to have a look as soon as I can find some time but I cannot do it right now.

Nope, reinstalled composer using global, it still worked ...

I've probably made something different than you because the composer directory ended up in the /home instead of at the root. But it worked anyway.

vagrant@dev-project:/vagrant/project$ php /home/vagrant/.composer/vendor/phpcheckstyle/phpcheckstyle/run.php --src ./website/
src --outdir ./build/reports/checkstyle_result/ --config default.cfg.xml --format html,xml --exclude Tests --linecount

Summary
=======

Errors:   6
Ignores:  0
Infos:    3
Warnings: 279
=======

Reporting Completed.

Can it be something else like a problem with a read permission on a file or something that makes the PHPCheckstyle class invisible ?

Just to be sure: did you also remove phpcheckstyle from the local vendor directory after requiring it globally? I added a var_dump(get_included_files()) in the run.php file, to check which autoload.php was loaded just before line 172, and it read only the project autoload.php (in my case it is the /app/vendor/autoload.php file), which will not find the PHPCheckstyle class unless it is present in the local vendor directory as well.

Yes, it was removed.

Strange that it found the autoload file, don't know what might be the difference then. Should I be testing against the master branch or the latest release commit 21ceb84?

Oh yes, i've been testing with the master branch.

I just tried it against dev-master, the error changed to line 196, but it still cannot find the class PHPCheckstyle:

Fatal error: Uncaught Error: Class 'PHPCheckstyle\PHPCheckstyle' not found in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php:196
Stack trace:
#0 {main}
  thrown in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php on line 196

I'll look into providing a simple example later (after hours), if that's okay?

okay ^^

Simple example, will install git, composer, phpcheckstyle, and run it against the ./src directory.

cat <<EOF > ./phpcheckstyle
    apk --update --quiet add git
    export COMPOSER_ALLOW_SUPERUSER=1
    export COMPOSER_HOME="/composer"
    curl -s https://getcomposer.org/installer -o /tmp/composer-setup.php
    curl -s https://composer.github.io/installer.sig -o /tmp/composer-setup.sig
    php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') !== trim(file_get_contents('/tmp/composer-setup.sig'))) { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    php /tmp/composer-setup.php --quiet --no-ansi --install-dir=/usr/local/bin --filename=composer
    php -r "unlink('/tmp/composer-setup.php');"
    php -r "unlink('/tmp/composer-setup.sig');"
    composer global require --dev phpcheckstyle/phpcheckstyle:dev-master
    php \${COMPOSER_HOME}/vendor/phpcheckstyle/phpcheckstyle/run.php --src ./src
EOF
docker run --rm -ti --entrypoint "" --volume $PWD:/app --volume composer:/composer --workdir /app php:7.1-alpine sh phpcheckstyle
rm -f ./phpcheckstyle

Throws as error:

Fatal error: Uncaught Error: Class 'PHPCheckstyle\PHPCheckstyle' not found in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php:196
Stack trace:
#0 {main}
  thrown in /composer/vendor/phpcheckstyle/phpcheckstyle/run.php on line 196

Edit: this runs on Mac OS bash with "docker for mac"

Can you reproduce it with this example?

Sorry, I have been quite busy lately, I havn't touched this project for a while.

All the tests I've done where on a Vagrant Box with Debian, and I havn't been able to reproduce the problem so far. I'll do some more tests when I can find so time.

I've done the install using the same command : composer global require --dev phpcheckstyle/phpcheckstyle:dev-master but I still cannot reproduce the problem.