feat: Add tag support to file history display
- Modified cvs_client.py get_file_history() to parse and extract tags from CVS log - Updated ui.js displayHistory() to render tags for each revision - Added CSS styling for history tags with proper theming support - Tags are displayed inline with revision information in history view
This commit is contained in:
parent
c15b759378
commit
45ad8bb135
3 changed files with 55 additions and 0 deletions
|
|
@ -232,6 +232,7 @@ class CVSClient:
|
||||||
revisions = []
|
revisions = []
|
||||||
current_revision = {}
|
current_revision = {}
|
||||||
in_log = False
|
in_log = False
|
||||||
|
in_tags = False
|
||||||
|
|
||||||
for line in output.split('\n'):
|
for line in output.split('\n'):
|
||||||
# Look for revision lines (format: "revision X.X")
|
# Look for revision lines (format: "revision X.X")
|
||||||
|
|
@ -240,12 +241,19 @@ class CVSClient:
|
||||||
# Look for date/author/state line (format: "date: YYYY/MM/DD HH:MM:SS; author: NAME; state: STATE;")
|
# Look for date/author/state line (format: "date: YYYY/MM/DD HH:MM:SS; author: NAME; state: STATE;")
|
||||||
date_match = re.match(r'^date:\s+(\d{4}/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2});\s+author:\s+(\S+);\s+state:\s+(\S+);', line)
|
date_match = re.match(r'^date:\s+(\d{4}/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2});\s+author:\s+(\S+);\s+state:\s+(\S+);', line)
|
||||||
|
|
||||||
|
# Look for branches line (format: "branches: ...")
|
||||||
|
branches_match = re.match(r'^branches:', line)
|
||||||
|
|
||||||
|
# Look for tag lines (format: "\tTAG_NAME: X.X")
|
||||||
|
tag_match = re.match(r'^\s+(\S+):\s+(\S+)', line)
|
||||||
|
|
||||||
if rev_match:
|
if rev_match:
|
||||||
# Start of a new revision
|
# Start of a new revision
|
||||||
if current_revision and 'revision' in current_revision:
|
if current_revision and 'revision' in current_revision:
|
||||||
revisions.append(current_revision)
|
revisions.append(current_revision)
|
||||||
current_revision = {'revision': rev_match.group(1)}
|
current_revision = {'revision': rev_match.group(1)}
|
||||||
in_log = False
|
in_log = False
|
||||||
|
in_tags = False
|
||||||
|
|
||||||
if date_match:
|
if date_match:
|
||||||
current_revision.update({
|
current_revision.update({
|
||||||
|
|
@ -255,11 +263,29 @@ class CVSClient:
|
||||||
'lines_changed': 'N/A' # cvs log doesn't provide line counts
|
'lines_changed': 'N/A' # cvs log doesn't provide line counts
|
||||||
})
|
})
|
||||||
in_log = False
|
in_log = False
|
||||||
|
in_tags = False
|
||||||
|
|
||||||
|
if branches_match:
|
||||||
|
# Branches section starts, tags follow
|
||||||
|
in_tags = True
|
||||||
|
in_log = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Capture tags (lines with indentation after branches line)
|
||||||
|
if in_tags and tag_match and not re.match(r'^---', line):
|
||||||
|
tag_name = tag_match.group(1)
|
||||||
|
tag_revision = tag_match.group(2)
|
||||||
|
# Only add tags that match the current revision
|
||||||
|
if tag_revision == current_revision.get('revision'):
|
||||||
|
if 'tags' not in current_revision:
|
||||||
|
current_revision['tags'] = []
|
||||||
|
current_revision['tags'].append(tag_name)
|
||||||
|
|
||||||
# Capture log message (lines after date/author/state until next revision or separator)
|
# Capture log message (lines after date/author/state until next revision or separator)
|
||||||
if in_log:
|
if in_log:
|
||||||
if line.strip() == '' or re.match(r'^---', line):
|
if line.strip() == '' or re.match(r'^---', line):
|
||||||
in_log = False
|
in_log = False
|
||||||
|
in_tags = False
|
||||||
elif not re.match(r'^(revision|date|branches):', line):
|
elif not re.match(r'^(revision|date|branches):', line):
|
||||||
if 'log' not in current_revision:
|
if 'log' not in current_revision:
|
||||||
current_revision['log'] = ''
|
current_revision['log'] = ''
|
||||||
|
|
@ -282,6 +308,9 @@ class CVSClient:
|
||||||
rev['log'] = rev['log'].strip().split('\n')[0]
|
rev['log'] = rev['log'].strip().split('\n')[0]
|
||||||
else:
|
else:
|
||||||
rev['log'] = ''
|
rev['log'] = ''
|
||||||
|
# Ensure tags field exists
|
||||||
|
if 'tags' not in rev:
|
||||||
|
rev['tags'] = []
|
||||||
|
|
||||||
return revisions
|
return revisions
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,31 @@ main {
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.history-tags {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.125rem 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-item.active .history-tag {
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
/* Patchset View */
|
/* Patchset View */
|
||||||
.patchset-content {
|
.patchset-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
||||||
1
ui/ui.js
1
ui/ui.js
|
|
@ -244,6 +244,7 @@ class UIManager {
|
||||||
<div class="history-log-section">
|
<div class="history-log-section">
|
||||||
<div class="history-log">${revision.log ? this.escapeHtml(revision.log) : ''}</div>
|
<div class="history-log">${revision.log ? this.escapeHtml(revision.log) : ''}</div>
|
||||||
${revision.state && revision.state !== 'Exp' ? `<span class="history-state">${revision.state}</span>` : ''}
|
${revision.state && revision.state !== 'Exp' ? `<span class="history-state">${revision.state}</span>` : ''}
|
||||||
|
${revision.tags && revision.tags.length > 0 ? `<span class="history-tags">${revision.tags.map(tag => `<span class="history-tag">${this.escapeHtml(tag)}</span>`).join('')}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="history-author">${revision.author || 'Unknown'}</div>
|
<div class="history-author">${revision.author || 'Unknown'}</div>
|
||||||
<div class="history-date" title="${revision.date || 'N/A'}">${this.getRelativeDate(revision.date) || 'N/A'}</div>
|
<div class="history-date" title="${revision.date || 'N/A'}">${this.getRelativeDate(revision.date) || 'N/A'}</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue