Programming

Install PHP CodeSniffer with PEAR

This article should be useful for other tools than CodeSniffer. To put some context, I installed PEAR some time ago for PHPUnit, before I read that PHPUnit had moved away from PEAR and can now be installed using Composer or a simple PHAR (PHp ARchive) file. I had troubles with the default PEAR configuration and the various steps to add the right folders in the system $PATH, PHP configuration, ... and my stubbornness to have everything exactly where I want and behave exactly the way I want!

On my Arch Linux system, PEAR install its packages by default in /usr/bin. I prefer to put them in /usr/share/pear/bin to be more restrictive on what folders I include in my PHP configuration and avoid including the whole /usr/bin in the open_basedir directive. As a reminder, PEAR is installed on Arch Linux with

$ yaourt -S php-pear

and should be available on most distributions through their respective package manager.

First, if, like me, you make 20 mistakes before doing something right, this is the command for uninstalling a package:

$ sudo pear uninstall <packagename></packagename>

To change the PEAR executables directory globally:

$ sudo pear config-set bin_dir /usr/share/pear/bin/

Don't use sudo if you want to apply the changes locally. In this case, it should create, I think automatically, a hidden file named .pearrc in your home directory.

We can check PEAR configuration with

$ sudo pear config-show

Output of $ pear config-show

We can now install CodeSniffer:

$ sudo pear install PHP_CodeSniffer

and adapt our PATH to find its executable by adding the following in our ~/.bashrc: PATH=/usr/share/pear/bin:$PATH.

We reload our config and check if the CodeSniffer executable is found in the right place:

$ . ~/.bashrc
$ whereis phpcs

Output of $ whereis phpcs

I use the open_basedir directive to add a bit of security. Of course, I don't remember that kind of details but PHP reminds me:

Error thrown by phpcs with open_basedir restriction

We fix this by editing /etc/php/php.ini or wherever your PHP configuration file is by adding the PEAR folder: open_basedir = /srv/http/:/tmp/:/usr/share/pear/.

We can now start refactoring...

$ phpcs path/to/file.php|js|css or $ phpcs path/to/folder

Example of output from phpcs

The following command:

$ phpcs -sp --encoding=utf-8 --standard=PSR2 --tab-width=4 --ignore={External/,Tests/coverage/} -v .

  • shows sniff codes, e.g.: (PSR2.Namespaces.UseDeclaration.SpaceAfterLastUse)
  • shows progress
  • specifies that the encoding of the files is utf-8
  • only uses the PSR-2 standard
  • specifies the number of spaces I use as tab
  • ignores the sub folders External and Tests/coverage
  • prints one level of verbosity
  • and processes the current folder.

How to restore a branch deleted too quickly in Git?

Having still not the automatic reflexes for applying a successful Git branching model, I cleaned up my working repository a little too fast by deleting a hot-fix branch after merging it into the master branch.

$ git branch -d hotfix-2014062501 
Deleted branch hotfix-2014062501 (was 742134c).

When I came back to the development branch I was working on before the emergency, I realised that I just forgot to merge the hot-fix into it.

As often with Git, a simple solution exists. We only need the sha1 of that branch last commit, which was conveniently displayed in the output of the deletion command above, and execute this one-liner:

$ git branch hotfix-2014062501 742134c

The branch should now be back as if nothing happened:

$ git branch -v
[...]
hotfix-2014062501        742134c some helpful comment

Source

Git refusing to delete a remote branch because it is set as current

I wanted to do some clean-up on a remote repository, which contained a lot of obsolete branches. But one of them returned the following error:

$ git push origin :alpha
remote: error: By default, deleting the current branch is denied, because the next
remote: error: 'git clone' won't result in any file checked out, causing confusion.
remote: error: 
remote: error: You can set 'receive.denyDeleteCurrent' configuration variable to
remote: error: 'warn' or 'ignore' in the remote repository to allow deleting the
remote: error: current branch, with or without a warning message.
remote: error: 
remote: error: To squelch this message, you can set it to 'refuse'.
remote: error: refusing to delete the current branch: refs/heads/alpha
To remote_repository_uri.git
 ! [remote rejected] alpha (deletion of the current branch prohibited)
error: failed to push some refs to 'remote_repository_uri.git'

As this verbose message explains, I was trying to delete the branch named "alpha", which was set as the current branch on the remote repository.

It was an old branch untouched for several months and I don't know how it has been set to be the current branch instead of master. Since the remote is a bare repository, I could not execute the usual git checkout master command. The solution is to move HEAD, which is a symbolic link pointing to the current branch. To make that link point to the master branch, execute the following command on the remote server:

$ git symbolic-ref HEAD refs/heads/master

We can verify where HEAD is pointing to with the same git symbolic-ref command:

$ git symbolic-ref HEAD
refs/heads/master

Source

git-symbolic-ref Manual Page

Git: show all branches on a remote repository

The command below displays all the branches on the remote repository called "origin", including those that are not tracked locally. It also displays local branches configured to be pulled or pushed and their current state.

$ git remote show origin
* remote origin
  Fetch URL: my_repository_uri.git
  Push  URL: my_repository_uri.git
  HEAD branch: master
  Remote branches:
    development                     tracked
    master                          tracked
    [...]
  Local branches configured for 'git pull':
    development         merges with remote development
    master              merges with remote master
    [...]
  Local refs configured for 'git push':
    development pushes to development (up to date)
    master      pushes to master      (local out of date)
    [...]

Source

To list only the branches that are tracked locally, use:

$ git branch -r
origin/development
origin/master
[...]

Execute a specific version of PHP on OVH shared server from command line

The first step is to find the right executable. For example, the default PHP executable is still in version 5.3.16:

$ php -v
[...]
PHP 5.3.16 (cgi-fcgi) (built: Aug 27 2012 17:36:50)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

Other versions are available and we have to specify them explicitly, as we do for Apache through an .htaccess file. My scripts need at least PHP 5.4 and, to use it in CLI, we need the following executable:

$ php.ORIG.5_4 -v
Fatal error:  Directive 'allow_call_time_pass_reference' is no longer available in PHP in Unknown on line 0

OK, we found it but it crashes right away because of the default configuration. To make it work properly, we need to add a flew flags:

$ php.ORIG.5_4 -d allow_call_time_pass_reference=0 -d magic_quotes_gpc=0 -d register_globals=0 /path/to/script.php