mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-01-22 19:01:02 +01:00
116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
# git/operations/revert.py
|
|
|
|
import git
|
|
import os
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def revert_file(repo_path, file_path):
|
|
"""
|
|
Revert changes in a file, handling tracked files, staged deletions, and new files.
|
|
|
|
Args:
|
|
repo_path: Path to the git repository
|
|
file_path: Path to the file to revert
|
|
|
|
Returns:
|
|
tuple: (success: bool, message: str)
|
|
"""
|
|
try:
|
|
repo = git.Repo(repo_path)
|
|
file_absolute_path = os.path.join(repo_path, file_path)
|
|
|
|
# Check if file is untracked (new)
|
|
untracked_files = repo.untracked_files
|
|
is_untracked = any(f == file_path for f in untracked_files)
|
|
|
|
# Check if file is staged for deletion
|
|
staged_deletions = repo.index.diff("HEAD", R=True)
|
|
is_staged_for_deletion = any(d.a_path == file_path
|
|
for d in staged_deletions)
|
|
|
|
if is_untracked:
|
|
# For untracked files, we need to remove them
|
|
try:
|
|
os.remove(file_absolute_path)
|
|
message = f"New file {file_path} has been removed."
|
|
except FileNotFoundError:
|
|
message = f"File {file_path} was already removed."
|
|
elif is_staged_for_deletion:
|
|
# Restore file staged for deletion
|
|
repo.git.reset("--", file_path)
|
|
repo.git.checkout('HEAD', "--", file_path)
|
|
message = f"File {file_path} has been restored and unstaged from deletion."
|
|
else:
|
|
# Regular revert for tracked files with changes
|
|
repo.git.restore("--", file_path)
|
|
repo.git.restore('--staged', "--", file_path)
|
|
message = f"File {file_path} has been reverted."
|
|
|
|
# Reload cache after ANY revert operation
|
|
from ...data.cache import data_cache
|
|
data_cache.initialize(force_reload=True)
|
|
|
|
return True, message
|
|
|
|
except git.exc.GitCommandError as e:
|
|
error_msg = str(e)
|
|
if "pathspec" in error_msg and "did not match any file(s) known to git" in error_msg:
|
|
logger.error(f"File {file_path} not found in git repository")
|
|
return False, f"File {file_path} not found in git repository"
|
|
logger.error(f"Git error reverting file: {error_msg}", exc_info=True)
|
|
return False, f"Git error reverting file: {error_msg}"
|
|
except Exception as e:
|
|
logger.error(f"Error reverting file: {str(e)}", exc_info=True)
|
|
return False, f"Error reverting file: {str(e)}"
|
|
|
|
|
|
def revert_all(repo_path):
|
|
"""
|
|
Revert all changes in the repository, including new files.
|
|
|
|
Args:
|
|
repo_path: Path to the git repository
|
|
|
|
Returns:
|
|
tuple: (success: bool, message: str)
|
|
"""
|
|
try:
|
|
repo = git.Repo(repo_path)
|
|
|
|
# First, clean untracked files
|
|
untracked_files = repo.untracked_files
|
|
for file_path in untracked_files:
|
|
try:
|
|
os.remove(os.path.join(repo_path, file_path))
|
|
except FileNotFoundError:
|
|
continue
|
|
except Exception as e:
|
|
logger.warning(
|
|
f"Could not remove untracked file {file_path}: {str(e)}")
|
|
|
|
# Then restore tracked files
|
|
repo.git.restore('--staged', '.')
|
|
repo.git.restore('.')
|
|
|
|
message = "All changes have been reverted to the last commit"
|
|
if untracked_files:
|
|
message += f" and {len(untracked_files)} new file(s) have been removed"
|
|
message += "."
|
|
|
|
# Reload cache after reverting all
|
|
from ...data.cache import data_cache
|
|
data_cache.initialize(force_reload=True)
|
|
|
|
return True, message
|
|
|
|
except git.exc.GitCommandError as e:
|
|
logger.error(f"Git error reverting all changes: {str(e)}",
|
|
exc_info=True)
|
|
return False, f"Git error reverting all changes: {str(e)}"
|
|
except Exception as e:
|
|
logger.error(f"Error reverting all changes: {str(e)}", exc_info=True)
|
|
return False, f"Error reverting all changes: {str(e)}"
|