1: <?php
2: /**
3: * Horde_Pear_Package_Contents_Ignore_Git:: indicates which files in a content
4: * listing should be ignored based on the contents from a .gitignore file.
5: *
6: * PHP version 5
7: *
8: * @category Horde
9: * @package Pear
10: * @author Gunnar Wrobel <wrobel@pardus.de>
11: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
12: * @link http://pear.horde.org/index.php?package=Pear
13: */
14:
15: /**
16: * Horde_Pear_Package_Contents_Ignore_Git:: indicates which files in a content
17: * listing should be ignored based on the contents from a .gitignore file.
18: *
19: * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
20: *
21: * See the enclosed file COPYING for license information (LGPL). If you
22: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
23: *
24: * @category Horde
25: * @package Pear
26: * @author Gunnar Wrobel <wrobel@pardus.de>
27: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
28: * @link http://pear.horde.org/index.php?package=Pear
29: */
30: class Horde_Pear_Package_Contents_Ignore_Git
31: implements Horde_Pear_Package_Contents_Ignore
32: {
33: /**
34: * The regular expressions for ignored files.
35: *
36: * @var array
37: */
38: private $_ignore = array();
39:
40: /**
41: * The regular expressions for files to exclude from ignoring.
42: *
43: * @var array
44: */
45: private $_include = array();
46:
47: /**
48: * The root position of the repository.
49: *
50: * @var string
51: */
52: private $_root;
53:
54: /**
55: * Constructor.
56: *
57: * @param string $gitignore The gitignore information
58:
59: * @param string $root The root position for the files that should be
60: * checked.
61: */
62: public function __construct($gitignore, $root)
63: {
64: $this->_root = $root;
65: $this->_prepare($gitignore);
66: }
67:
68: /**
69: * Prepare the list of ignores and includes from the gitignore input.
70: *
71: * @param string $gitignore The content of the .gitignore file.
72: *
73: * @return NULL
74: */
75: private function _prepare($gitignore)
76: {
77: foreach (explode("\n", $gitignore) as $line) {
78: $line = strtr($line, ' ', '');
79: if (empty($line) || strpos($line, '#') === 0) {
80: continue;
81: }
82: if (strpos($line, '!') === 0) {
83: $this->_include[] = $this->_getRegExpableSearchString(
84: substr($line, 1)
85: );
86: } else {
87: $this->_ignore[] = $this->_getRegExpableSearchString($line);
88: }
89: }
90: }
91:
92: /**
93: * Return the list of ignored patterns.
94: *
95: * @return array The list of patterns.
96: */
97: public function getIgnores()
98: {
99: return $this->_ignore;
100: }
101:
102: /**
103: * Return the list of included patterns.
104: *
105: * @return array The list of patterns.
106: */
107: public function getIncludes()
108: {
109: return $this->_include;
110: }
111:
112: /**
113: * Tell whether to ignore the element.
114: *
115: * @param SplFileInfo $element The element to check.
116: *
117: * @return bool True if the element should be ignored, false otherwise.
118: */
119: public function isIgnored(SplFileInfo $element)
120: {
121: $rooted_path = substr($element->getPathname(), strlen($this->_root));
122: if ($this->_matches($this->_ignore, $rooted_path)
123: && !$this->_matches($this->_include, $rooted_path)) {
124: return true;
125: }
126: return false;
127: }
128:
129: /**
130: * Does the given path match one of the regular expression patterns?
131: *
132: * @param array $matches The regular expression patterns.
133: * @param string $path The file path.
134: *
135: * @return NULL
136: */
137: private function _matches($matches, $path)
138: {
139: foreach ($matches as $match) {
140: preg_match('/' . $match.'/', $path, $find);
141: if (count($find)) {
142: return true;
143: }
144: }
145: return false;
146: }
147:
148: /**
149: * Converts $s into a string that can be used with preg_match
150: *
151: * @param string $s string with wildcards ? and *
152: *
153: * @return string converts * to .*, ? to ., etc.
154: */
155: private function _getRegExpableSearchString($s)
156: {
157: if ($s[0] == DIRECTORY_SEPARATOR) {
158: $pre = '^';
159: } else {
160: $pre = '.*';
161: }
162:
163: $x = strtr(
164: $s,
165: array(
166: '?' => '.',
167: '*' => '[^\/]*',
168: '.' => '\\.',
169: '\\' => '\\\\',
170: '/' => '\\/',
171: '-' => '\\-'
172: )
173: );
174:
175: if (substr($s, strlen($s) - 1) == DIRECTORY_SEPARATOR) {
176: $post = '.*';
177: } else {
178: $post = '$';
179: }
180:
181: return $pre . $x . $post;
182: }
183: }