1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20: class Horde_Vcs_Svn extends Horde_Vcs_Base
21: {
22: 23: 24: 25: 26:
27: protected $_driver = 'Svn';
28:
29: 30: 31: 32: 33:
34: protected $_features = array(
35: 'deleted' => false,
36: 'patchsets' => true,
37: 'branches' => false,
38: 'snapshots' => false);
39:
40: 41: 42: 43: 44:
45: protected $_username = '';
46:
47: 48: 49: 50: 51:
52: protected $_password = '';
53:
54: 55: 56: 57: 58:
59: public function __construct($params = array())
60: {
61: if (!empty($params['username'])) {
62: $this->_username = $params['username'];
63: }
64:
65: if (!empty($params['password'])) {
66: $this->_password = $params['password'];
67: }
68: parent::__construct($params);
69: }
70:
71: 72: 73:
74: public function getCommand()
75: {
76: $svnPath = $this->getPath('svn');
77: $tempDir = isset($this->_paths['svn_home'])
78: ? $this->_paths['svn_home']
79: : Horde_Util::getTempDir();
80: $command = $svnPath . ' --non-interactive --config-dir ' . $tempDir;
81:
82: if ($this->_username) {
83: $command .= ' --username ' . $this->_username;
84: }
85:
86: if ($this->_password) {
87: $command .= ' --password ' . $this->_password;
88: }
89:
90: return $command;
91: }
92:
93: 94: 95:
96: public function annotate($fileob, $rev)
97: {
98: $this->assertValidRevision($rev);
99:
100: $command = $this->getCommand() . ' annotate -r ' . escapeshellarg('1:' . $rev) . ' ' . escapeshellarg($fileob->getPath()) . ' 2>&1';
101: $pipe = popen($command, 'r');
102: if (!$pipe) {
103: throw new Horde_Vcs_Exception('Failed to execute svn annotate: ' . $command);
104: }
105:
106: $lines = array();
107: $lineno = 1;
108:
109: while (!feof($pipe)) {
110: $line = fgets($pipe, 4096);
111: if (preg_match('/^\s+(\d+)\s+([\w\.]+)\s(.*)$/', $line, $regs)) {
112: $lines[] = array(
113: 'rev' => $regs[1],
114: 'author' => trim($regs[2]),
115: 'date' => '',
116: 'line' => $regs[3],
117: 'lineno' => $lineno++
118: );
119: }
120: }
121:
122: pclose($pipe);
123: return $lines;
124: }
125:
126: 127: 128: 129: 130: 131: 132: 133: 134: 135:
136: public function checkout($fullname, $rev)
137: {
138: $this->assertValidRevision($rev);
139:
140: if ($RCS = popen($this->getCommand() . ' cat -r ' . escapeshellarg($rev) . ' ' . escapeshellarg($fullname) . ' 2>&1', VC_WINDOWS ? 'rb' : 'r')) {
141: return $RCS;
142: }
143:
144: throw new Horde_Vcs_Exception('Couldn\'t perform checkout of the requested file');
145: }
146:
147: 148: 149:
150: public function isValidRevision($rev)
151: {
152: return $rev && (string)(int)$rev == $rev;
153: }
154:
155: 156: 157: 158: 159: 160: 161: 162: 163: 164:
165: public function getRevisionRange(Horde_Vcs_File_Base $file, $r1, $r2)
166: {
167:
168: }
169:
170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184:
185: protected function _diff(Horde_Vcs_File_Base $file, $rev1, $rev2, $opts)
186: {
187: $diff = array();
188: $flags = '';
189:
190: if (!$opts['ws']) {
191: $flags .= ' -bB ';
192: }
193:
194: switch ($opts['type']) {
195: case 'context':
196: $flags .= '--context=' . (int)$opts['num'];
197: break;
198:
199: case 'unified':
200: $flags .= '-p --unified=' . (int)$opts['num'];
201: break;
202:
203: case 'column':
204: $flags .= '--side-by-side --width=120';
205: break;
206:
207: case 'ed':
208: $flags .= '-e';
209: break;
210: }
211:
212:
213:
214: $command = $this->getCommand() . " diff --diff-cmd " . $this->getPath('diff') . ' -r ' . escapeshellarg($rev1 . ':' . $rev2) . ' -x ' . escapeshellarg($flags) . ' ' . escapeshellarg($file->getPath()) . ' 2>&1';
215:
216: exec($command, $diff, $retval);
217: return $diff;
218: }
219: }
220: