diff --git a/backend/app/settings.py b/backend/app/settings.py index 6c13270..edd1673 100644 --- a/backend/app/settings.py +++ b/backend/app/settings.py @@ -69,36 +69,6 @@ def validate_git_token(repo_url, git_token): except Exception as e: return False -def parse_diff(diff_text): - diff_lines = diff_text.splitlines() - parsed_diff = [] - - local_version = [] - incoming_version = [] - in_local = False - in_incoming = False - - for line in diff_lines: - if line.startswith('--- a/'): - in_local = True - in_incoming = False - elif line.startswith('+++ b/'): - in_incoming = True - in_local = False - elif line.startswith('@@'): - # Context lines that indicate a change - parsed_diff.append({'context': line, 'type': 'context'}) - elif line.startswith('-'): - local_version.append(line[1:]) - parsed_diff.append({'text': line[1:], 'type': 'local'}) - elif line.startswith('+'): - incoming_version.append(line[1:]) - parsed_diff.append({'text': line[1:], 'type': 'incoming'}) - else: - parsed_diff.append({'text': line, 'type': 'unchanged'}) - - return parsed_diff, local_version, incoming_version - def get_outgoing_changes(repo): status = repo.git.status('--porcelain', '-z').split('\0') logger.debug(f"Raw porcelain status: {status}") @@ -119,7 +89,19 @@ def get_outgoing_changes(repo): full_path = os.path.join(repo.working_dir, file_path) - if os.path.isdir(full_path): + if x == 'D' or y == 'D': + # Handle deleted files + changes.append({ + 'name': 'Deleted File', + 'id': '', + 'type': determine_type(file_path), + 'status': 'Deleted', + 'file_path': file_path, + 'staged': x != '?', + 'modified': False, + 'deleted': True + }) + elif os.path.isdir(full_path): logger.debug(f"Found directory: {file_path}, going through folder.") for root, dirs, files in os.walk(full_path): for file in files: @@ -139,17 +121,14 @@ def get_outgoing_changes(repo): 'file_path': os.path.relpath(file_full_path, repo.working_dir), 'staged': x != '?' and x != ' ', 'modified': y == 'M', - 'deleted': x == 'D' or y == 'D' + 'deleted': False }) else: logger.debug(f"No data extracted from file: {file_full_path}") else: logger.debug(f"Found file: {full_path}, going through file.") file_data = extract_data_from_yaml(full_path) - if file_data or x == 'D' or y == 'D': # Ensure that deleted files are handled - if not file_data: - logger.debug(f"No data found, using default file name as name") - file_data = {'name': os.path.basename(file_path).replace('.yml', ''), 'id': None} + if file_data: logger.debug(f"File contents: {file_data}") logger.debug(f"Found ID: {file_data.get('id')}") logger.debug(f"Found Name: {file_data.get('name')}") @@ -161,7 +140,19 @@ def get_outgoing_changes(repo): 'file_path': file_path, 'staged': x != '?' and x != ' ', 'modified': y == 'M', - 'deleted': x == 'D' or y == 'D' + 'deleted': False + }) + else: + logger.debug(f"No data found, using default file name as name") + changes.append({ + 'name': os.path.basename(file_path).replace('.yml', ''), + 'id': '', + 'type': determine_type(file_path), + 'status': interpret_git_status(x, y), + 'file_path': file_path, + 'staged': x != '?' and x != ' ', + 'modified': y == 'M', + 'deleted': False }) logger.debug(f"Final changes: {json.dumps(changes, indent=2)}") @@ -772,8 +763,23 @@ def get_diff(): try: repo = git.Repo(settings_manager.repo_path) branch = repo.active_branch.name - diff = repo.git.diff(f'HEAD...origin/{branch}', file_path) - return jsonify({'success': True, 'diff': diff}), 200 + + # Check if the file is untracked + untracked_files = repo.untracked_files + if file_path in untracked_files: + with open(os.path.join(repo.working_dir, file_path), 'r') as file: + content = file.read() + diff = "\n".join([f"+{line}" for line in content.splitlines()]) + else: + # Check if the file is deleted + if not os.path.exists(os.path.join(repo.working_dir, file_path)): + diff = "-Deleted File" + else: + # Get the diff for modified files + diff = repo.git.diff(f'HEAD', file_path) + + logger.debug(f"Diff for file {file_path}: {diff}") + return jsonify({'success': True, 'diff': diff if diff else ""}), 200 except Exception as e: logger.error(f"Error getting diff for file {file_path}: {str(e)}", exc_info=True) - return jsonify({'success': False, 'error': f"Error getting diff for file: {str(e)}"}), 400 + return jsonify({'success': False, 'error': f"Error getting diff for file: {str(e)}"}), 400 \ No newline at end of file diff --git a/frontend/src/components/settings/DiffModal.jsx b/frontend/src/components/settings/DiffModal.jsx index 2848090..d58c800 100644 --- a/frontend/src/components/settings/DiffModal.jsx +++ b/frontend/src/components/settings/DiffModal.jsx @@ -1,87 +1,86 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Modal from '../ui/Modal'; -import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; -import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'; +import React from "react"; +import PropTypes from "prop-types"; +import Modal from "../ui/Modal"; -const DiffModal = ({ isOpen, onClose, diffContent, type, name, commitMessage, title = "View Diff" }) => { - const formatDiffContent = (content) => { - return content - .split('\n') - .filter(line => - !line.startsWith('diff --git') && - !line.startsWith('index') && - !line.startsWith('---') && - !line.startsWith('+++') && - !line.startsWith('@@') - ) - .map((line, index) => { - let className = 'pl-2'; - let lineBackground = ''; - - if (line.startsWith('+')) { - className += ' text-green-400'; // Green for additions - lineBackground = 'bg-green-900'; // Darker green background - } else if (line.startsWith('-')) { - className += ' text-red-400'; // Red for deletions - lineBackground = 'bg-red-900'; // Darker red background - } else if (line.startsWith('@@')) { - className += ' text-yellow-400'; // Yellow for diff hunk headers - lineBackground = 'bg-gray-700'; // Neutral background - } else { - lineBackground = 'bg-gray-800'; // Default background for unchanged lines - } - - return ( -
- {index + 1} - {line} -
- ); - }); - }; - - +const DiffModal = ({ + isOpen, + onClose, + diffContent, + type, + name, + commitMessage, + title = "View Diff", +}) => { + const formatDiffContent = (content) => { + if (!content) return []; + return content.split("\n").map((line, index) => { + let lineClass = "py-1 pl-4 border-l-2 "; + if (line.startsWith("+")) { + lineClass += "bg-green-900/30 text-green-400 border-green-500"; + } else if (line.startsWith("-")) { + lineClass += "bg-red-900/30 text-red-400 border-red-500"; + } else { + lineClass += "border-transparent"; + } + return ( +
+ + {index + 1} + + {line} +
+ ); + }); + }; + + const formattedContent = formatDiffContent(diffContent); return ( - -
-
-
- Type: - {type} + +
+
+
+ + Type: + + + {type} +
-
- Name: - {name} +
+ + Name: + + + {name === "Deleted File" ? "Deleted File" : name} +
{commitMessage && ( -
- Commit Message: - {commitMessage} +
+ + Commit Message: + +

+ {commitMessage} +

)}
+
+
+ Diff Content +
+
+ {formattedContent.length > 0 ? ( + formattedContent + ) : ( +
+ No differences found or file is empty. +
+ )} +
+
-
-
- {formatDiffContent(diffContent || "No differences found.")} -
-
- ); }; @@ -89,7 +88,7 @@ const DiffModal = ({ isOpen, onClose, diffContent, type, name, commitMessage, ti DiffModal.propTypes = { isOpen: PropTypes.bool.isRequired, onClose: PropTypes.func.isRequired, - diffContent: PropTypes.string.isRequired, + diffContent: PropTypes.string, type: PropTypes.string.isRequired, name: PropTypes.string.isRequired, commitMessage: PropTypes.string, diff --git a/frontend/src/components/settings/DiffViewer.jsx b/frontend/src/components/settings/DiffViewer.jsx deleted file mode 100644 index f33e12d..0000000 --- a/frontend/src/components/settings/DiffViewer.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import Modal from '../ui/Modal'; - -const DiffViewer = ({ isOpen, onClose, diffContent = [] }) => { - // Ensure diffContent is an array before proceeding - if (!Array.isArray(diffContent)) { - diffContent = []; // Default to an empty array if diffContent is not an array - } - - // Separate content for local and incoming - const localContent = diffContent.filter(line => line.type === 'local' || line.type === 'context' || line.type === 'unchanged'); - const incomingContent = diffContent.filter(line => line.type === 'incoming' || line.type === 'context' || line.type === 'unchanged'); - - const renderDiffColumn = (content) => { - return content.map((line, index) => { - let lineClass = 'text-gray-200'; // Default line class for unchanged lines - - if (line.type === 'local') { - lineClass = 'bg-red-400 text-black'; // Highlight local changes - } else if (line.type === 'incoming') { - lineClass = 'bg-yellow-400 text-black'; // Highlight incoming changes - } else if (line.type === 'context') { - lineClass = 'text-gray-400'; // Context lines - } - - return ( -
- {line.text} -
- ); - }); - }; - - return ( - -
-
-

Remote

-
- {renderDiffColumn(localContent)} -
-
-
-

Local

-
- {renderDiffColumn(incomingContent)} -
-
-
-
- ); -}; - -export default DiffViewer; diff --git a/frontend/src/components/settings/SettingsPage.jsx b/frontend/src/components/settings/SettingsPage.jsx index 3f1d809..79b5d21 100644 --- a/frontend/src/components/settings/SettingsPage.jsx +++ b/frontend/src/components/settings/SettingsPage.jsx @@ -289,13 +289,15 @@ const SettingsPage = () => { }; const handleViewDiff = async (change) => { - setLoadingDiff(true); // Start loading + setLoadingDiff(true); try { const response = await getDiff(change.file_path); + console.log("Diff response:", response); // Add this line to log the response if (response.success) { - setDiffContent(response.diff); // Store the diff content - setCurrentChange(change); // Set the current change being viewed - setShowDiffModal(true); // Open the modal + console.log("Diff content:", response.diff); // Add this line to log the diff content + setDiffContent(response.diff); + setCurrentChange(change); + setShowDiffModal(true); } else { Alert.error(response.error); } @@ -303,7 +305,7 @@ const SettingsPage = () => { Alert.error("An unexpected error occurred while fetching the diff."); console.error("Error fetching diff:", error); } finally { - setLoadingDiff(false); // Stop loading + setLoadingDiff(false); setLoadingAction(""); } };