Skip to content
This repository was archived by the owner on Dec 8, 2017. It is now read-only.

Commit 21098ae

Browse files
committed
Merge pull request #42 from shadowhand/feature/commit-message-review
Add commit message review
2 parents b4d3e38 + 91543c9 commit 21098ae

24 files changed

Lines changed: 749 additions & 21 deletions

README.md

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ $ bin/static-review.php hook:install hooks/example-pre-commit.php ~/.../.git/hoo
3838

3939
[composer]: https://getcomposer.org/
4040

41-
## Example Hook
41+
## Example Hooks
4242

43-
Below is a basic hook that you can extend upon.
43+
Static Review can be used for both files and commit message review. Below are
44+
basic hooks for each.
45+
46+
### For Files
4447

4548
```php
4649
#!/usr/bin/env php
@@ -50,6 +53,7 @@ include __DIR__ . '/../../../autoload.php';
5053

5154
// Reference the required classes.
5255
use StaticReview\StaticReview;
56+
use StaticReview\Review\General\LineEndingsReview;
5357
[...]
5458

5559
$reporter = new Reporter();
@@ -61,17 +65,47 @@ $review->addReview(new LineEndingsReview());
6165
$git = new GitVersionControl();
6266

6367
// Review the staged files.
64-
$review->review($git->getStagedFiles());
68+
$review->files($git->getStagedFiles());
6569

6670
// Check if any issues were found.
6771
// Exit with a non-zero status to block the commit.
6872
($reporter->hasIssues()) ? exit(1) : exit(0);
6973
```
7074

71-
## Example Review
75+
### For Commit Messages
7276

7377
```php
74-
class NoCommitTagReview extends AbstractReview
78+
#!/usr/bin/env php
79+
<?php
80+
81+
include __DIR__ . '/../../../autoload.php';
82+
83+
// Reference the required classes.
84+
use StaticReview\StaticReview;
85+
use StaticReview\Review\Message\BodyLineLengthReview;
86+
[...]
87+
88+
$reporter = new Reporter();
89+
$review = new StaticReview($reporter);
90+
91+
// Add any reviews to the StaticReview instance, supports a fluent interface.
92+
$review->addReview(new BodyLineLengthReview());
93+
94+
$git = new GitVersionControl();
95+
96+
// Review the current commit message.
97+
// The hook is passed the file holding the commit message as the first argument.
98+
$review->message($git->getCommitMessage($argv[1]));
99+
100+
// Check if any issues were found.
101+
// Exit with a non-zero status to block the commit.
102+
($reporter->hasIssues()) ? exit(1) : exit(0);
103+
```
104+
105+
## Example Review For Files
106+
107+
```php
108+
class NoCommitTagReview extends AbstractFileReview
75109
{
76110
// Review any text based file.
77111
public function canReviewFile(FileInterface $file)
@@ -98,6 +132,24 @@ class NoCommitTagReview extends AbstractReview
98132
}
99133
```
100134

135+
## Example Review For Messages
136+
137+
```php
138+
class WorkInProgressReview extends AbstractMessageReview
139+
{
140+
// Check if the commit message contains "wip"
141+
public function review(ReporterInterface $reporter, ReviewableInterface $commit)
142+
{
143+
$fulltext = $commit->getSubject() . PHP_EOL . $commit->getBody();
144+
145+
if (preg_match('/\bwip\b/i', $fulltext)) {
146+
$message = 'Do not commit WIP to shared branches';
147+
$reporter->error($message, $this, $commit);
148+
}
149+
}
150+
}
151+
```
152+
101153
## Unit Tests
102154

103155
See [vagrantup.com][vagrant] and [phpunit.de][phpunit].

hooks/static-review-commit-msg.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
/*
5+
* This file is part of StaticReview
6+
*
7+
* Copyright (c) 2015 Woody Gilk <@shadowhand>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*
12+
* @see http://github.com/sjparkinson/static-review/blob/master/LICENSE
13+
*/
14+
15+
$included = include file_exists(__DIR__ . '/../vendor/autoload.php')
16+
? __DIR__ . '/../vendor/autoload.php'
17+
: __DIR__ . '/../../../autoload.php';
18+
19+
if (! $included) {
20+
echo 'You must set up the project dependencies, run the following commands:' . PHP_EOL
21+
. 'curl -sS https://getcomposer.org/installer | php' . PHP_EOL
22+
. 'php composer.phar install' . PHP_EOL;
23+
24+
exit(1);
25+
}
26+
27+
if (empty($argv[1]) || !is_file($argv[1])) {
28+
echo 'WARNING: Skipping commit message check because the Git hook was not ' . PHP_EOL
29+
. 'passed the commit message file path; normally `.git/COMMIT_EDITMSG`' . PHP_EOL;
30+
31+
exit(1);
32+
}
33+
34+
// Reference the required classes and the reviews you want to use.
35+
use League\CLImate\CLImate;
36+
use StaticReview\Issue\Issue;
37+
use StaticReview\Reporter\Reporter;
38+
use StaticReview\Review\Message\BodyLineLengthReview;
39+
use StaticReview\Review\Message\SubjectImperativeReview;
40+
use StaticReview\Review\Message\SubjectLineCapitalReview;
41+
use StaticReview\Review\Message\SubjectLineLengthReview;
42+
use StaticReview\Review\Message\SubjectLinePeriodReview;
43+
use StaticReview\Review\Message\WorkInProgressReview;
44+
use StaticReview\StaticReview;
45+
use StaticReview\VersionControl\GitVersionControl;
46+
47+
$reporter = new Reporter();
48+
$climate = new CLImate();
49+
$git = new GitVersionControl();
50+
51+
$review = new StaticReview($reporter);
52+
53+
// Add any reviews to the StaticReview instance, supports a fluent interface.
54+
$review->addReview(new BodyLineLengthReview())
55+
->addReview(new SubjectImperativeReview())
56+
->addReview(new SubjectLineCapitalReview())
57+
->addReview(new SubjectLineLengthReview())
58+
->addReview(new SubjectLinePeriodReview())
59+
->addReview(new WorkInProgressReview());
60+
61+
// Check the commit message.
62+
$review->message($git->getCommitMessage($argv[1]));
63+
64+
// Check if any matching issues were found.
65+
if ($reporter->hasIssues()) {
66+
$climate->out('')->out('');
67+
68+
foreach ($reporter->getIssues() as $issue) {
69+
$climate->red($issue);
70+
}
71+
72+
$climate->out('')->red('✘ Please fix the errors above.');
73+
74+
exit(1);
75+
76+
} else {
77+
$climate->green('✔ That commit looks good!');
78+
79+
exit(0);
80+
}

src/Collection/ReviewCollection.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace StaticReview\Collection;
1515

16+
use StaticReview\Commit\CommitMessageInterface;
1617
use StaticReview\File\FileInterface;
1718
use StaticReview\Review\ReviewInterface;
1819

@@ -69,4 +70,24 @@ public function forFile(FileInterface $file)
6970

7071
return $this->select($filter);
7172
}
73+
74+
/**
75+
* Returns a filtered ReviewCollection that should be run against the given
76+
* message.
77+
*
78+
* @param CommitMessage $message
79+
* @return ReviewCollection
80+
*/
81+
public function forMessage(CommitMessageInterface $message)
82+
{
83+
$filter = function ($review) use ($message) {
84+
if ($review->canReview($message)) {
85+
return true;
86+
}
87+
88+
return false;
89+
};
90+
91+
return $this->select($filter);
92+
}
7293
}

src/Commit/CommitMessage.php

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
/*
4+
* This file is part of StaticReview
5+
*
6+
* Copyright (c) 2014 Samuel Parkinson <@samparkinson_>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @see http://github.com/sjparkinson/static-review/blob/master/LICENSE
12+
*/
13+
14+
namespace StaticReview\Commit;
15+
16+
class CommitMessage implements CommitMessageInterface
17+
{
18+
/**
19+
* @var string Commit message subject.
20+
*/
21+
protected $subject;
22+
23+
/**
24+
* @var string Commit message body.
25+
*/
26+
protected $body = '';
27+
28+
/**
29+
* @var boolean Commit identifier.
30+
*/
31+
protected $hash;
32+
33+
/**
34+
* Initializes a new instance of the CommitMessage class.
35+
*
36+
* @param string $message
37+
* @param string $hash
38+
*/
39+
public function __construct($message, $hash = null)
40+
{
41+
$message = preg_replace('/^#.*/m', '', $message);
42+
$message = preg_split('/(\r?\n)+/', trim($message));
43+
44+
$this->subject = array_shift($message);
45+
46+
if ($message) {
47+
$this->body = implode("\n", $message);
48+
}
49+
50+
$this->hash = $hash;
51+
}
52+
53+
/**
54+
* Get the commit message subject.
55+
*
56+
* @return string
57+
*/
58+
public function getSubject()
59+
{
60+
return $this->subject;
61+
}
62+
63+
/**
64+
* Get the commit message body.
65+
*
66+
* @return string
67+
*/
68+
public function getBody()
69+
{
70+
return $this->body;
71+
}
72+
73+
/**
74+
* Is the commit current or historical?
75+
*
76+
* @return string|null
77+
*/
78+
public function getHash()
79+
{
80+
return $this->hash ?: null;
81+
}
82+
83+
/**
84+
* Get the reviewable name for the commit.
85+
*
86+
* @return string
87+
*/
88+
public function getName()
89+
{
90+
return $this->getHash() ?: 'current commit';
91+
}
92+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of StaticReview
5+
*
6+
* Copyright (c) 2015 Woody Gilk <@shadowhand>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @see http://github.com/sjparkinson/static-review/blob/master/LICENSE
12+
*/
13+
14+
namespace StaticReview\Commit;
15+
16+
use StaticReview\Review\ReviewableInterface;
17+
18+
interface CommitMessageInterface extends ReviewableInterface
19+
{
20+
public function getSubject();
21+
22+
public function getBody();
23+
24+
public function getHash();
25+
}

src/Review/AbstractFileReview.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of StaticReview
5+
*
6+
* Copyright (c) 2015 Woody Gilk <@shadowhand>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @see http://github.com/sjparkinson/static-review/blob/master/LICENSE
12+
*/
13+
14+
namespace StaticReview\Review;
15+
16+
use StaticReview\Commit\CommitMessageInterface;
17+
use Symfony\Component\Process\Process;
18+
19+
abstract class AbstractFileReview extends AbstractReview
20+
{
21+
protected function canReviewMessage(CommitMessageInterface $message)
22+
{
23+
return false;
24+
}
25+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of StaticReview
5+
*
6+
* Copyright (c) 2015 Woody Gilk <@shadowhand>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @see http://github.com/sjparkinson/static-review/blob/master/LICENSE
12+
*/
13+
14+
namespace StaticReview\Review;
15+
16+
use StaticReview\Commit\CommitMessageInterface;
17+
use StaticReview\File\FileInterface;
18+
use Symfony\Component\Process\Process;
19+
20+
abstract class AbstractMessageReview extends AbstractReview
21+
{
22+
protected function canReviewFile(FileInterface $file)
23+
{
24+
return false;
25+
}
26+
27+
protected function canReviewMessage(CommitMessageInterface $message)
28+
{
29+
return true;
30+
}
31+
}

0 commit comments

Comments
 (0)