Overview

Packages

  • None
  • Vcs

Classes

  • Horde_Vcs
  • Horde_Vcs_Base
  • Horde_Vcs_Cvs
  • Horde_Vcs_Directory_Base
  • Horde_Vcs_Directory_Cvs
  • Horde_Vcs_Directory_Git
  • Horde_Vcs_Directory_Rcs
  • Horde_Vcs_Directory_Svn
  • Horde_Vcs_File_Base
  • Horde_Vcs_File_Cvs
  • Horde_Vcs_File_Git
  • Horde_Vcs_File_Rcs
  • Horde_Vcs_File_Svn
  • Horde_Vcs_Git
  • Horde_Vcs_Log_Base
  • Horde_Vcs_Log_Cvs
  • Horde_Vcs_Log_Git
  • Horde_Vcs_Log_Rcs
  • Horde_Vcs_Log_Svn
  • Horde_Vcs_Patchset
  • Horde_Vcs_Patchset_Base
  • Horde_Vcs_Patchset_Cvs
  • Horde_Vcs_Patchset_Git
  • Horde_Vcs_Patchset_Svn
  • Horde_Vcs_QuickLog_Base
  • Horde_Vcs_QuickLog_Cvs
  • Horde_Vcs_QuickLog_Git
  • Horde_Vcs_QuickLog_Rcs
  • Horde_Vcs_QuickLog_Svn
  • Horde_Vcs_Rcs
  • Horde_Vcs_Svn
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Git file class.
  4:  *
  5:  * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author  Chuck Hagenbuch <chuck@horde.org>
 11:  * @author  Michael Slusarz <slusarz@horde.org>
 12:  * @package Vcs
 13:  */
 14: class Horde_Vcs_File_Git extends Horde_Vcs_File_Base
 15: {
 16:     /**
 17:      * The current driver.
 18:      *
 19:      * @var string
 20:      */
 21:     protected $_driver = 'Git';
 22: 
 23:     /**
 24:      * The master list of revisions for this file.
 25:      *
 26:      * @var array
 27:      */
 28:     protected $_revlist = array();
 29: 
 30:     protected function _init()
 31:     {
 32:         /* First, grab the master list of revisions. */
 33:         if (version_compare($this->_rep->version, '1.6.0', '>=')) {
 34:             $cmd = 'rev-list --branches -- '
 35:                 . escapeshellarg($this->getSourcerootPath());
 36:         } else {
 37:             list($stream, $result) = $this->_rep->runCommand(
 38:                 'branch -v --no-abbrev');
 39:             $branch_heads = array();
 40:             while (!feof($result)) {
 41:                 $line = explode(' ', substr(rtrim(fgets($result)), 2));
 42:                 $branch_heads[] = $line[1];
 43:             }
 44:             fclose($result);
 45:             proc_close($stream);
 46: 
 47:             $cmd = 'rev-list ' . implode(' ', $branch_heads) . ' -- '
 48:                 . escapeshellarg($this->getSourcerootPath());
 49:         }
 50: 
 51:         list($stream, $result) = $this->_rep->runCommand($cmd);
 52:         while (!feof($result)) {
 53:             $line = trim(fgets($result));
 54:             if (strlen($line)) {
 55:                 $this->_revs[] = $line;
 56:             }
 57:         }
 58:         fclose($result);
 59:         proc_close($stream);
 60: 
 61:         if (!$this->_revs) {
 62:             $branch = empty($this->_branch) ? null : $this->_branch;
 63:             if (!$this->_rep->isFile($this->getSourcerootPath(), $branch)) {
 64:                 throw new Horde_Vcs_Exception('No such file: ' . $this->getSourcerootPath());
 65:             } else {
 66:                 throw new Horde_Vcs_Exception('No revisions found');
 67:             }
 68:         }
 69: 
 70:         $branchlist = empty($this->_branch)
 71:             ? array_keys($this->getBranches())
 72:             : array($this->_branch);
 73: 
 74:         /* First, get all revisions at once. */
 75:         $log_list = null;
 76:         $cmd = 'rev-list';
 77:         foreach ($branchlist as $branch) {
 78:             $cmd .= ' ' . escapeshellarg($branch);
 79:         }
 80:         $cmd .= ' -- ' . escapeshellarg($this->getSourcerootPath());
 81:         list($stream, $result) = $this->_rep->runCommand($cmd);
 82: 
 83:         if (!feof($result)) {
 84:             $revs = explode("\n", trim(stream_get_contents($result)));
 85:             $log_list = $revs;
 86:         }
 87:         fclose($result);
 88:         proc_close($stream);
 89: 
 90:         if (is_null($log_list)) {
 91:             $log_list = empty($this->_branch) ? $this->_revs : array();
 92:         }
 93:         foreach ($log_list as $val) {
 94:             $this->_logs[$val] = $this->_getLog($val);
 95:         }
 96: 
 97:         /* Next, get all revisions per branch. */
 98:         $cmd = 'rev-list %s -- ' . escapeshellarg($this->getSourcerootPath());
 99:         foreach ($branchlist as $branch) {
100:             list($stream, $result) = $this->_rep->runCommand(
101:                 sprintf($cmd, escapeshellarg($branch)));
102:             if (!feof($result)) {
103:                 $revs = explode("\n", trim(stream_get_contents($result)));
104:                 $this->_revlist[$branch] = $revs;
105:             }
106:             fclose($result);
107:             proc_close($stream);
108:         }
109:     }
110: 
111:     /**
112:      * Returns the last revision of the current file on the HEAD branch.
113:      *
114:      * @return string  Last revision of the current file.
115:      * @throws Horde_Vcs_Exception
116:      */
117:     public function getRevision()
118:     {
119:         $this->_ensureInitialized();
120:         if (empty($this->_branch)) {
121:             return parent::getRevision();
122:         }
123: 
124:         $rev = reset($this->_revlist[$this->_branch]);
125:         if (is_null($rev)) {
126:             throw new Horde_Vcs_Exception('No revisions');
127:         }
128: 
129:         return $rev;
130:     }
131: 
132:     /**
133:      * Returns the revision before the specified revision.
134:      *
135:      * @param string $rev  A revision.
136:      *
137:      * @return string  The previous revision or null if the first revision.
138:      */
139:     public function getPreviousRevision($rev)
140:     {
141:         $this->_ensureInitialized();
142: 
143:         if (empty($this->_branch)) {
144:             return parent::getPreviousRevision($rev);
145:         }
146: 
147:         $key = array_search($rev, $this->_revlist[$this->_branch]);
148:         return ($key !== false &&
149:                 isset($this->_revlist[$this->_branch][$key + 1]))
150:             ? $this->_revlist[$this->_branch][$key + 1]
151:             : null;
152:     }
153: 
154:     /**
155:      * Get the hash name for this file at a specific revision.
156:      *
157:      * @param string $rev  Revision string.
158:      *
159:      * @return string  Commit hash.
160:      */
161:     public function getHashForRevision($rev)
162:     {
163:         $this->_ensureInitialized();
164:         if (!isset($this->_logs[$rev])) {
165:             throw new Horde_Vcs_Exception('This file doesn\'t exist at that revision');
166:         }
167:         return $this->_logs[$rev]->getHashForPath($this->getSourcerootPath());
168:     }
169: 
170:     /**
171:      * TODO
172:      */
173:     public function getBranchList()
174:     {
175:         return $this->_revlist;
176:     }
177: 
178:     /**
179:      * Returns all branches that contain a certain revision.
180:      *
181:      * @param string $rev  A revision.
182:      *
183:      * @return array  A list of branches with this revision.
184:      */
185:     public function getBranch($rev)
186:     {
187:         $branches = array();
188: 
189:         foreach (array_keys($this->_revlist) as $val) {
190:             if (array_search($rev, $this->_revlist[$val]) !== false) {
191:                 $branches[] = $val;
192:             }
193:         }
194: 
195:         return $branches;
196:     }
197: 
198:     /**
199:      * Return the "base" filename (i.e. the filename needed by the various
200:      * command line utilities).
201:      *
202:      * @return string  A filename.
203:      */
204:     public function getPath()
205:     {
206:         return $this->getSourcerootPath();
207:     }
208: 
209:     /**
210:      * TODO
211:      */
212:     public function getBranches()
213:     {
214:         /* If dealing with a branch that is not explicitly named (i.e. an
215:          * implicit branch for a given tree-ish commit ID), we need to add
216:          * that information to the branch list. */
217:         $revlist = $this->_rep->getBranchList();
218:         if (!empty($this->_branch) &&
219:             !in_array($this->_branch, $revlist)) {
220:             $revlist[$this->_branch] = $this->_branch;
221:         }
222:         return $revlist;
223:     }
224: 
225:     /**
226:      * TODO
227:      */
228:     public function getLog($rev = null)
229:     {
230:         if (is_null($rev)) {
231:             $this->_ensureInitialized();
232:             return $this->_logs;
233:         } else {
234:             if (!isset($this->_logs[$rev])) {
235:                 $this->_logs[$rev] = $this->_getLog($rev);
236:             }
237: 
238:             return isset($this->_logs[$rev]) ? $this->_logs[$rev] : null;
239:         }
240:     }
241: 
242:     /**
243:      * Returns a log object for the most recent log entry of this file.
244:      *
245:      * @return Horde_Vcs_QuickLog_Git  Log object of the last entry in the file.
246:      * @throws Horde_Vcs_Exception
247:      */
248:     public function getLastLog()
249:     {
250:         $branch = empty($this->_branch)
251:             ? $this->_rep->getDefaultBranch()
252:             : $this->_branch;
253:         $cmd = 'rev-list -n 1 ' . escapeshellarg($branch)
254:             . ' -- ' . escapeshellarg($this->getSourcerootPath());
255:         list($stream, $result) = $this->_rep->runCommand($cmd);
256:         $rev = trim(fgets($result));
257:         fclose($result);
258:         proc_close($stream);
259:         return new Horde_Vcs_QuickLog_Git($this->_rep, $rev);
260:     }
261: 
262:     /**
263:      * TODO
264:      */
265:     public function revisionCount()
266:     {
267:         if (empty($this->_branch)) {
268:             return parent::revisionCount();
269:         }
270:         $this->_ensureInitialized();
271:         return count($this->_revlist[$this->_branch]);
272:     }
273: 
274:     /**
275:      * TODO
276:      */
277:     public function getTags()
278:     {
279:         list($stream, $result) = $this->_rep->runCommand('show-ref --tags');
280:         $tags = array();
281:         while (!feof($result)) {
282:             $line = trim(fgets($result));
283:             if ($line) {
284:                 list($rev, $tag) = explode(' ', $line);
285:                 $tags[basename($tag)] = $rev;
286:             }
287:         }
288:         fclose($result);
289:         proc_close($stream);
290:         return $tags;
291:     }
292: }
293: 
API documentation generated by ApiGen