| | |
| | $tags = []; |
| | + $repoParam = '&repo=' . urlencode($this->currentRepo['safe_name']); |
| | |
| | // 1. Collect tags and parse dates |
| | $this->git->eachTag(function($name, $sha) use (&$tags) { |
| | + // Read the object to peel tags and get dates |
| | $data = $this->git->read($sha); |
| | $targetSha = $sha; |
| | $timestamp = 0; |
| | |
| | - // Check if Annotated Tag |
| | + // Check if Annotated Tag (starts with 'object <sha>') |
| | if (strncmp($data, 'object ', 7) === 0) { |
| | - if (preg_match('/^object ([0-9a-f]{40})$/m', $data, $matches)) { |
| | - $targetSha = $matches[1]; |
| | - } |
| | - if (preg_match('/^tagger .* (\d+) [+\-]\d{4}$/m', $data, $matches)) { |
| | - $timestamp = (int)$matches[1]; |
| | - } |
| | + // Extract target SHA |
| | + if (preg_match('/^object ([0-9a-f]{40})$/m', $data, $matches)) { |
| | + $targetSha = $matches[1]; |
| | + } |
| | + // Extract Tagger Date |
| | + if (preg_match('/^tagger .* (\d+) [+\-]\d{4}$/m', $data, $matches)) { |
| | + $timestamp = (int)$matches[1]; |
| | + } |
| | } |
| | - // Lightweight Tag |
| | + // Lightweight Tag (Commit object) |
| | else { |
| | - if (preg_match('/^author .* (\d+) [+\-]\d{4}$/m', $data, $matches)) { |
| | - $timestamp = (int)$matches[1]; |
| | - } |
| | + // Extract Author Date |
| | + if (preg_match('/^author .* (\d+) [+\-]\d{4}$/m', $data, $matches)) { |
| | + $timestamp = (int)$matches[1]; |
| | + } |
| | } |
| | |
| | $tags[] = [ |
| | - 'name' => $name, |
| | - 'sha' => $sha, |
| | - 'targetSha' => $targetSha, |
| | - 'timestamp' => $timestamp |
| | + 'name' => $name, |
| | + 'sha' => $sha, |
| | + 'targetSha' => $targetSha, |
| | + 'timestamp' => $timestamp |
| | ]; |
| | }); |
| | |
| | // 2. Sort by date descending (newest first) |
| | usort($tags, function($a, $b) { |
| | - return $b['timestamp'] <=> $a['timestamp']; |
| | + return $b['timestamp'] <=> $a['timestamp']; |
| | }); |
| | |
| | // 3. Render |
| | if (empty($tags)) { |
| | echo '<div class="empty-state"><p>No tags found.</p></div>'; |
| | } else { |
| | - $repoParam = '&repo=' . urlencode($this->currentRepo['safe_name']); |
| | - |
| | foreach ($tags as $tag) { |
| | - $dateStr = $tag['timestamp'] ? date('Y-M-d', $tag['timestamp']) : ''; |
| | - $filesUrl = '?hash=' . $tag['targetSha'] . $repoParam; |
| | - $commitUrl = '?action=commit&hash=' . $tag['targetSha'] . $repoParam; |
| | + $dateStr = $tag['timestamp'] ? date('Y-M-d', $tag['timestamp']) : ''; |
| | + $filesUrl = '?hash=' . $tag['targetSha'] . $repoParam; |
| | + $commitUrl = '?action=commit&hash=' . $tag['targetSha'] . $repoParam; |
| | |
| | - echo '<div class="ref-item">'; |
| | - echo '<span class="ref-type tag">Tag</span>'; |
| | - echo '<a href="' . $filesUrl . '" class="ref-name">' . htmlspecialchars($tag['name']) . '</a>'; |
| | + echo '<div class="ref-item">'; |
| | + // "Tag" label removed here |
| | + echo '<a href="' . $filesUrl . '" class="ref-name">' . htmlspecialchars($tag['name']) . '</a>'; |
| | |
| | - if ($dateStr) { |
| | - echo '<span class="commit-date" style="margin-left: auto; margin-right: 15px;">' . $dateStr . '</span>'; |
| | - } |
| | + if ($dateStr) { |
| | + echo '<span class="commit-date" style="margin-left: auto; margin-right: 15px;">' . $dateStr . '</span>'; |
| | + } |
| | |
| | - echo '<a href="' . $commitUrl . '" class="commit-hash" ' . (!$dateStr ? 'style="margin-left: auto;"' : '') . '>' . substr($tag['sha'], 0, 7) . '</a>'; |
| | - echo '</div>'; |
| | + // We display the Tag SHA, but link to the Commit SHA |
| | + echo '<a href="' . $commitUrl . '" class="commit-hash" ' . (!$dateStr ? 'style="margin-left: auto;"' : '') . '>' . substr($tag['sha'], 0, 7) . '</a>'; |
| | + echo '</div>'; |
| | } |
| | } |