mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-28 13:30:56 +01:00
feat: improved parsing of commit message in backend
This commit is contained in:
@@ -2,33 +2,50 @@
|
||||
|
||||
import os
|
||||
import logging
|
||||
from .utils import extract_data_from_yaml, determine_type
|
||||
from .utils import extract_data_from_yaml, determine_type, parse_commit_message
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_incoming_changes(repo, branch):
|
||||
incoming_changes = []
|
||||
diff = repo.git.diff(f'HEAD...origin/{branch}', name_only=True)
|
||||
changed_files = diff.split('\n') if diff else []
|
||||
|
||||
|
||||
for file_path in changed_files:
|
||||
if file_path:
|
||||
full_path = os.path.join(repo.working_dir, file_path)
|
||||
file_data = extract_data_from_yaml(full_path) if os.path.exists(full_path) else None
|
||||
|
||||
file_data = extract_data_from_yaml(full_path) if os.path.exists(
|
||||
full_path) else None
|
||||
|
||||
# Correcting the git show command
|
||||
commit_message = repo.git.show(f'HEAD...origin/{branch}', '--format=%B', '-s', file_path).strip()
|
||||
|
||||
raw_commit_message = repo.git.show(f'HEAD...origin/{branch}',
|
||||
'--format=%B', '-s',
|
||||
file_path).strip()
|
||||
parsed_commit_message = parse_commit_message(
|
||||
raw_commit_message
|
||||
) # Parse commit message using the util function
|
||||
|
||||
incoming_changes.append({
|
||||
'name': file_data.get('name', os.path.basename(file_path)) if file_data else os.path.basename(file_path),
|
||||
'id': file_data.get('id') if file_data else None,
|
||||
'type': determine_type(file_path),
|
||||
'status': 'Incoming',
|
||||
'file_path': file_path,
|
||||
'commit_message': commit_message, # Include commit message here
|
||||
'staged': False,
|
||||
'modified': True,
|
||||
'deleted': False
|
||||
'name':
|
||||
file_data.get('name', os.path.basename(file_path))
|
||||
if file_data else os.path.basename(file_path),
|
||||
'id':
|
||||
file_data.get('id') if file_data else None,
|
||||
'type':
|
||||
determine_type(file_path),
|
||||
'status':
|
||||
'Incoming',
|
||||
'file_path':
|
||||
file_path,
|
||||
'commit_message':
|
||||
parsed_commit_message, # Use parsed commit message
|
||||
'staged':
|
||||
False,
|
||||
'modified':
|
||||
True,
|
||||
'deleted':
|
||||
False
|
||||
})
|
||||
|
||||
return incoming_changes
|
||||
|
||||
return incoming_changes
|
||||
|
||||
@@ -3,31 +3,34 @@
|
||||
import os
|
||||
import yaml
|
||||
import logging
|
||||
import re
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def extract_data_from_yaml(file_path):
|
||||
logger.debug(f"Extracting data from file: {file_path}")
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
content = yaml.safe_load(f)
|
||||
logger.debug(f"File content: {content}") # Log the full file content
|
||||
logger.debug(
|
||||
f"File content: {content}") # Log the full file content
|
||||
if content is None:
|
||||
logger.error(f"Failed to parse YAML file or file is empty: {file_path}")
|
||||
logger.error(
|
||||
f"Failed to parse YAML file or file is empty: {file_path}")
|
||||
return None
|
||||
|
||||
|
||||
# Check if expected keys are in the content
|
||||
if 'name' not in content or 'id' not in content:
|
||||
logger.warning(f"'name' or 'id' not found in file: {file_path}")
|
||||
|
||||
return {
|
||||
'name': content.get('name'),
|
||||
'id': content.get('id')
|
||||
}
|
||||
logger.warning(
|
||||
f"'name' or 'id' not found in file: {file_path}")
|
||||
|
||||
return {'name': content.get('name'), 'id': content.get('id')}
|
||||
except Exception as e:
|
||||
logger.warning(f"Error reading file {file_path}: {str(e)}")
|
||||
return None
|
||||
|
||||
|
||||
def determine_type(file_path):
|
||||
if 'regex_patterns' in file_path:
|
||||
return 'Regex Pattern'
|
||||
@@ -37,6 +40,7 @@ def determine_type(file_path):
|
||||
return 'Quality Profile'
|
||||
return 'Unknown'
|
||||
|
||||
|
||||
def interpret_git_status(x, y):
|
||||
if x == 'D' or y == 'D':
|
||||
return 'Deleted'
|
||||
@@ -54,3 +58,89 @@ def interpret_git_status(x, y):
|
||||
return 'Untracked'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
|
||||
def parse_commit_message(commit_message):
|
||||
# Default placeholders for missing parts of the commit message
|
||||
placeholders = {
|
||||
'type': 'Unknown Type',
|
||||
'scope': 'Unknown Scope',
|
||||
'subject': 'No subject provided',
|
||||
'body': 'No body provided',
|
||||
'footer': 'No footer provided'
|
||||
}
|
||||
|
||||
# Mapping of commit types and scopes to canonical forms
|
||||
type_mapping = {
|
||||
'feat': 'New Feature',
|
||||
'feature': 'New Feature',
|
||||
'new': 'New Feature',
|
||||
'fix': 'BugFix',
|
||||
'bugfix': 'BugFix',
|
||||
'bug': 'BugFix',
|
||||
'docs': 'Documentation',
|
||||
'documentation': 'Documentation',
|
||||
'doc': 'Documentation',
|
||||
'style': 'Style Change',
|
||||
'formatting': 'Style Change',
|
||||
'format': 'Style Change',
|
||||
'lint': 'Style Change',
|
||||
'refactor': 'Refactor',
|
||||
'refactoring': 'Refactor',
|
||||
'restructure': 'Refactor',
|
||||
'redesign': 'Refactor',
|
||||
'perf': 'Performance Improvement',
|
||||
'performance': 'Performance Improvement',
|
||||
'optimize': 'Performance Improvement',
|
||||
'optimisation': 'Performance Improvement',
|
||||
'test': 'Test',
|
||||
'testing': 'Test',
|
||||
'chore': 'Maintenance',
|
||||
'maintenance': 'Maintenance',
|
||||
'maintain': 'Maintenance'
|
||||
}
|
||||
|
||||
scope_mapping = {
|
||||
'regex': 'Regex Pattern',
|
||||
'regex pattern': 'Regex Pattern',
|
||||
'format': 'Custom Format',
|
||||
'custom format': 'Custom Format',
|
||||
'profile': 'Quality Profile',
|
||||
'quality profile': 'Quality Profile'
|
||||
}
|
||||
|
||||
# Regex patterns for each part of the commit message
|
||||
type_pattern = r'^(?P<type>feat|feature|new|fix|bugfix|bug|docs|documentation|doc|style|formatting|format|lint|refactor|refactoring|restructure|redesign|perf|performance|optimize|optimisation|test|testing|chore|maintenance|maintain)'
|
||||
scope_pattern = r'\((?P<scope>regex|regex pattern|format|custom format|profile|quality profile)\)'
|
||||
subject_pattern = r':\s(?P<subject>.+)'
|
||||
body_pattern = r'(?P<body>(?:- .+\n?)+)' # Handles multiple lines in the body
|
||||
footer_pattern = r'(?P<footer>(Fixes|Resolves|See also|Relates to)\s.+)'
|
||||
|
||||
# Initialize result with placeholders
|
||||
parsed_message = placeholders.copy()
|
||||
|
||||
# Parse the type and scope
|
||||
type_scope_match = re.match(
|
||||
f'{type_pattern}{scope_pattern}{subject_pattern}', commit_message,
|
||||
re.IGNORECASE)
|
||||
if type_scope_match:
|
||||
matched_type = type_scope_match.group('type').lower()
|
||||
matched_scope = type_scope_match.group('scope').lower()
|
||||
|
||||
# Map the matched values to their canonical forms
|
||||
parsed_message['type'] = type_mapping.get(matched_type, 'Unknown Type')
|
||||
parsed_message['scope'] = scope_mapping.get(matched_scope,
|
||||
'Unknown Scope')
|
||||
parsed_message['subject'] = type_scope_match.group('subject').strip()
|
||||
|
||||
# Match and extract the body part
|
||||
body_match = re.search(body_pattern, commit_message, re.MULTILINE)
|
||||
if body_match:
|
||||
parsed_message['body'] = body_match.group('body').strip()
|
||||
|
||||
# Match and extract the footer (if present)
|
||||
footer_match = re.search(footer_pattern, commit_message)
|
||||
if footer_match:
|
||||
parsed_message['footer'] = footer_match.group('footer').strip()
|
||||
|
||||
return parsed_message
|
||||
|
||||
@@ -59,6 +59,7 @@ const ChangeRow = ({
|
||||
|
||||
const handleViewDiff = e => {
|
||||
e.stopPropagation();
|
||||
console.log('Change Object: ', JSON.stringify(change, null, 2));
|
||||
setShowDiff(true);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ import {GitCommit} from 'lucide-react';
|
||||
const DiffCommit = ({commitMessage}) => {
|
||||
if (!commitMessage) return null;
|
||||
|
||||
const [firstLine, ...restLines] = commitMessage.split('\n');
|
||||
const [commitType, commitSummary] = firstLine.split(': ');
|
||||
const {type, scope, subject, body, footer} = commitMessage;
|
||||
|
||||
return (
|
||||
<div className='bg-gray-100 dark:bg-gray-800 p-4 rounded-lg shadow-sm'>
|
||||
@@ -21,15 +20,15 @@ const DiffCommit = ({commitMessage}) => {
|
||||
</h4>
|
||||
<div className='mb-2'>
|
||||
<span className='inline-block px-2 py-1 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 mr-2'>
|
||||
{commitType}
|
||||
{type}
|
||||
</span>
|
||||
<span className='text-sm font-semibold text-gray-700 dark:text-gray-300'>
|
||||
{commitSummary}
|
||||
{`${scope ? `(${scope})` : ''} ${subject}`}
|
||||
</span>
|
||||
</div>
|
||||
{restLines.length > 0 && (
|
||||
{body && (
|
||||
<ul className='list-disc pl-5 space-y-1'>
|
||||
{restLines.map((line, index) => (
|
||||
{body.split('\n').map((line, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className='text-sm text-gray-600 dark:text-gray-400'>
|
||||
@@ -38,6 +37,11 @@ const DiffCommit = ({commitMessage}) => {
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{footer && (
|
||||
<div className='mt-2 text-sm text-gray-600 dark:text-gray-400'>
|
||||
{footer}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,7 +49,13 @@ const DiffCommit = ({commitMessage}) => {
|
||||
};
|
||||
|
||||
DiffCommit.propTypes = {
|
||||
commitMessage: PropTypes.string
|
||||
commitMessage: PropTypes.shape({
|
||||
type: PropTypes.string.isRequired,
|
||||
scope: PropTypes.string,
|
||||
subject: PropTypes.string.isRequired,
|
||||
body: PropTypes.string,
|
||||
footer: PropTypes.string
|
||||
})
|
||||
};
|
||||
|
||||
export default DiffCommit;
|
||||
|
||||
@@ -77,7 +77,8 @@ const ViewDiff = ({
|
||||
title={titleContent}
|
||||
size='4xl'>
|
||||
<div className='space-y-4'>
|
||||
<DiffCommit commitMessage={commitMessage} />
|
||||
<DiffCommit commitMessage={commitMessage} />{' '}
|
||||
{/* Passing the commitMessage object */}
|
||||
<div className='border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden'>
|
||||
<div className='bg-gray-50 dark:bg-gray-800 p-2 text-sm font-medium text-gray-600 dark:text-gray-300 border-b border-gray-300 dark:border-gray-600'>
|
||||
Diff Content
|
||||
@@ -103,7 +104,13 @@ ViewDiff.propTypes = {
|
||||
diffContent: PropTypes.string,
|
||||
type: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
commitMessage: PropTypes.string,
|
||||
commitMessage: PropTypes.shape({
|
||||
type: PropTypes.string,
|
||||
scope: PropTypes.string,
|
||||
subject: PropTypes.string,
|
||||
body: PropTypes.string,
|
||||
footer: PropTypes.string
|
||||
}),
|
||||
isIncoming: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user