/** * Instantiates object * * @param GitPHP_Project $project the project * @param string $hash pack hash * @param GitPHP_GitObjectLoader object loader */ public function __construct($project, $hash, $objectLoader) { if (!$project) { throw new Exception('Project is required'); } if (!preg_match('/[0-9A-Fa-f]{40}/', $hash)) { throw new GitPHP_InvalidHashException($hash); } if (!$objectLoader) { throw new Exception('Object loader is required'); } $this->hash = $hash; $this->packIndex = new GitPHP_PackIndex($project->GetPath() . '/objects/pack/pack-' . $hash . '.idx'); $this->packData = new GitPHP_PackData($project->GetPath() . '/objects/pack/pack-' . $hash . '.pack', $objectLoader); }
/** * Searches file contents for matches */ private function SearchFileContents() { $args = array(); $args[] = '-I'; $args[] = '--full-name'; $args[] = '--ignore-case'; $args[] = '-n'; $args[] = '-e'; $args[] = '"' . addslashes($this->search) . '"'; $args[] = $this->treeHash; $lines = explode("\n", $this->exe->Execute($this->project->GetPath(), GIT_GREP, $args)); foreach ($lines as $line) { if (preg_match('/^[^:]+:([^:]+):([0-9]+):(.+)$/', $line, $regs)) { if (isset($this->allResults[$regs[1]])) { $result = $this->allResults[$regs[1]]; $matchingLines = $result->GetMatchingLines(); $matchingLines[(int) $regs[2]] = trim($regs[3], "\n\r\v"); $result->SetMatchingLines($matchingLines); } else { $tree = $this->GetTree(); $hash = $tree->PathToHash($regs[1]); if ($hash) { $blob = $this->project->GetObjectManager()->GetBlob($hash); $blob->SetPath($regs[1]); $result = new GitPHP_FileSearchResult($this->project, $blob, $regs[1]); $matchingLines = array(); $matchingLines[(int) $regs[2]] = trim($regs[3], "\n\r\v"); $result->SetMatchingLines($matchingLines); $this->allResults[$regs[1]] = $result; } } } } }
/** * Loads the history data */ protected function LoadData() { $this->dataLoaded = true; $args = array(); $args[] = $this->hash; $args[] = '--no-merges'; $canSkip = true; if ($this->skip > 0) { $canSkip = $this->exe->CanSkip(); } if ($canSkip) { if ($this->limit > 0) { $args[] = '--max-count=' . $this->limit; } if ($this->skip > 0) { $args[] = '--skip=' . $this->skip; } } else { if ($this->limit > 0) { $args[] = '--max-count=' . ($this->limit + $this->skip); } } $args[] = '--'; $args[] = $this->path; $args[] = '|'; $args[] = $this->exe->GetBinary(); $args[] = '--git-dir=' . escapeshellarg($this->project->GetPath()); $args[] = GIT_DIFF_TREE; $args[] = '-r'; $args[] = '--stdin'; $args[] = '--'; $args[] = $this->path; $historylines = explode("\n", $this->exe->Execute($this->project->GetPath(), GIT_REV_LIST, $args)); $commitHash = null; foreach ($historylines as $line) { if (preg_match('/^([0-9a-fA-F]{40})/', $line, $regs)) { $commitHash = $regs[1]; } else { if ($commitHash) { try { $this->history[] = array('diffline' => $line, 'commithash' => $commitHash); } catch (Exception $e) { } $commitHash = null; } } } if ($this->skip > 0 && !$canSkip) { if ($this->limit > 0) { $this->history = array_slice($this->history, $this->skip, $this->limit); } else { $this->history = array_slice($this->history, $this->skip); } } }
/** * Execute rev-list command * * @param GitPHP_Project $project project * @param string $hash hash to look back from * @param int $count number to return (0 for all) * @param int $skip number of items to skip * @param array $args extra arguments */ public function RevList($project, $hash, $count, $skip = 0, $args = array()) { if (!$project || empty($hash)) { return; } $canSkip = true; if ($skip > 0) { $canSkip = $this->exe->CanSkip(); } $extraargs = array(); if ($canSkip) { if ($count > 0) { $extraargs[] = '--max-count=' . $count; } if ($skip > 0) { $extraargs[] = '--skip=' . $skip; } } else { if ($count > 0) { $extraargs[] = '--max-count=' . ($count + $skip); } } $extraargs[] = $hash; if (count($args) > 0) { $endarg = array_search('--', $args); if ($endarg !== false) { array_splice($args, $endarg, 0, $extraargs); } else { $args = array_merge($args, $extraargs); } } else { $args = $extraargs; } $revlist = explode("\n", $this->exe->Execute($project->GetPath(), GIT_REV_LIST, $args)); if (!$revlist[count($revlist) - 1]) { /* the last newline creates a null entry */ array_splice($revlist, -1, 1); } if ($skip > 0 && !$canSkip) { if ($count > 0) { return array_slice($revlist, $skip, $count); } else { return array_slice($revlist, $skip); } } return $revlist; }
/** * Load a project's head hash * * @param GitPHP_Project $project * @return string head hash */ public function LoadHead($project) { if (!$project) { return; } $headPointer = trim(file_get_contents($project->GetPath() . '/HEAD')); if (preg_match('/^([0-9A-Fa-f]{40})$/', $headPointer, $regs)) { /* Detached HEAD */ return $regs[1]; } else { if (preg_match('/^ref: (.+)$/', $headPointer, $regs)) { /* standard pointer to head */ $head = substr($regs[1], strlen('refs/heads/')); if ($project->GetHeadList()->Exists($head)) { return $project->GetHeadList()->GetHead($head)->GetHash(); } } } }
/** * Loads the blame data */ private function LoadData() { $this->dataLoaded = true; $args = array(); $args[] = '-s'; $args[] = '-l'; $args[] = $this->commitHash; $args[] = '--'; $args[] = $this->path; $blamelines = explode("\n", $this->exe->Execute($this->project->GetPath(), GIT_BLAME, $args)); $lastcommit = ''; foreach ($blamelines as $line) { if (preg_match('/^([0-9a-fA-F]{40})(\\s+.+)?\\s+([0-9]+)\\)/', $line, $regs)) { if ($regs[1] != $lastcommit) { $this->blame[(int) $regs[3]] = $regs[1]; $lastcommit = $regs[1]; } } } }
/** * Finds loose hash files matching a given prefix * * @param string $prefix hash prefix * @return string[] array of hashes */ private function FindHashObjects($prefix) { $matches = array(); if (empty($prefix)) { return $matches; } $subdir = substr($prefix, 0, 2); $fulldir = $this->project->GetPath() . '/objects/' . $subdir; if (!is_dir($fulldir)) { return $matches; } $prefixlen = strlen($prefix); $dh = opendir($fulldir); if ($dh !== false) { while (($file = readdir($dh)) !== false) { $fullhash = $subdir . $file; if (substr_compare($fullhash, $prefix, 0, $prefixlen) === 0) { $matches[] = $fullhash; } } } return $matches; }
public function testPath() { $project = new GitPHP_Project(GITPHP_TEST_PROJECTROOT, 'testrepo.git', $this->getMock('GitPHP_ProjectLoadStrategy_Interface')); $this->assertEquals(GITPHP_TEST_PROJECTROOT . '/testrepo.git', $project->GetPath()); }
/** * Abbreviate a hash * * @param GitPHP_Project $project project * @param string $hash hash to abbreviate * @return string abbreviated hash */ public function AbbreviateHash($project, $hash) { if (!$project) { return $hash; } if (!preg_match('/[0-9A-Fa-f]{40}/', $hash)) { return $hash; } $args = array(); $args[] = '-1'; $args[] = '--format=format:%h'; $args[] = $hash; $abbrevData = explode("\n", $this->exe->Execute($project->GetPath(), GIT_REV_LIST, $args)); if (empty($abbrevData[0])) { return $hash; } if (substr_compare(trim($abbrevData[0]), 'commit', 0, 6) !== 0) { return $hash; } if (empty($abbrevData[1])) { return $hash; } return trim($abbrevData[1]); }
/** * Loads a project * * @param string $proj project * @return GitPHP_Project project */ protected function LoadProject($proj) { try { $project = new GitPHP_Project($this->projectRoot, $proj); $category = trim(dirname($proj)); if (!(empty($category) || strpos($category, '.') === 0)) { $project->SetCategory($category); } if ($this->exportedOnly && !$project->GetDaemonEnabled()) { $this->Log('Project export disabled', $project->GetPath()); return null; } $this->ApplyGlobalConfig($project); $this->ApplyGitConfig($project); if ($this->projectSettings && isset($this->projectSettings[$proj])) { $this->ApplyProjectSettings($project, $this->projectSettings[$proj]); } $this->InjectProjectDependencies($project); return $project; } catch (Exception $e) { $this->Log('Project error', $e->getMessage()); } return null; }
/** * Reads the project's git config settings and applies them to the project * * @param GitPHP_Project $project project */ protected function ApplyGitConfig($project) { if (!$project) { return; } $config = null; try { $config = new GitPHP_GitConfig($project->GetPath() . '/config'); } catch (Exception $e) { return; } if ($config->HasValue('gitphp.owner')) { $project->SetOwner($config->GetValue('gitphp.owner')); } else { if ($config->HasValue('gitweb.owner')) { $project->SetOwner($config->GetValue('gitweb.owner')); } } if ($config->HasValue('gitphp.description')) { $project->SetDescription($config->GetValue('gitphp.description')); } else { if ($config->HasValue('gitweb.description')) { $project->SetDescription($config->GetValue('gitweb.description')); } } if ($config->HasValue('gitphp.category')) { $project->SetCategory($config->GetValue('gitphp.category')); } if ($config->HasValue('gitphp.cloneurl')) { $project->SetCloneUrl($config->GetValue('gitphp.cloneurl')); } if ($config->HasValue('gitphp.pushurl')) { $project->SetPushUrl($config->GetValue('gitphp.pushurl')); } if ($config->HasValue('gitphp.bugurl')) { $project->SetBugUrl($config->GetValue('gitphp.bugurl')); } if ($config->HasValue('gitphp.bugpattern')) { $project->SetBugPattern($config->GetValue('gitphp.bugpattern')); } if ($config->HasValue('gitphp.website')) { $project->SetWebsite($config->GetValue('gitphp.website')); } if ($config->HasValue('gitphp.compat')) { $project->SetCompat($config->GetValue('gitphp.compat')); } if ($config->HasValue('core.abbrev')) { $project->SetAbbreviateLength($config->GetValue('core.abbrev')); } if ($config->HasValue('gitphp.allowedusers')) { $project->SetAllowedUsers($config->GetValue('gitphp.allowedusers', true)); } }