@@ -31,6 +31,7 @@ def backup_repository(self, repository):
3131 db .session .add (backup_job )
3232 db .session .commit ()
3333
34+ temp_clone_dir = None
3435 try :
3536 # Create user-specific backup directory
3637 user_backup_dir = self .backup_base_dir / f"user_{ repository .user_id } "
@@ -44,39 +45,39 @@ def backup_repository(self, repository):
4445 timestamp = datetime .utcnow ().strftime ('%Y%m%d_%H%M%S' )
4546 backup_name = f"{ repository .name } _{ timestamp } "
4647
47- # Clone repository to temporary location
48+ # Create unique temporary directory and ensure it's clean
4849 temp_clone_dir = repo_backup_dir / f"temp_{ timestamp } "
50+
51+ # Remove temp directory if it already exists
52+ if temp_clone_dir .exists ():
53+ logger .warning (f"Temp directory already exists, removing: { temp_clone_dir } " )
54+ shutil .rmtree (temp_clone_dir )
55+
4956 temp_clone_dir .mkdir (exist_ok = True )
5057
51- try :
52- self ._clone_repository (repository , temp_clone_dir )
53-
54- # Create backup in specified format
55- backup_path = self ._create_backup (
56- temp_clone_dir ,
57- repo_backup_dir ,
58- backup_name ,
59- repository .backup_format
60- )
61-
62- # Clean up old backups based on retention policy
63- self ._cleanup_old_backups (repo_backup_dir , repository .retention_count , repository .backup_format )
64-
65- # Update backup job record
66- backup_job .status = 'completed'
67- backup_job .backup_path = str (backup_path )
68- backup_job .file_size = self ._get_file_size (backup_path )
69- backup_job .completed_at = datetime .utcnow ()
70-
71- # Update repository last backup time
72- repository .last_backup = datetime .utcnow ()
73-
74- logger .info (f"Backup completed successfully: { backup_path } " )
75-
76- finally :
77- # Always clean up temporary directory
78- if temp_clone_dir .exists ():
79- shutil .rmtree (temp_clone_dir )
58+ self ._clone_repository (repository , temp_clone_dir )
59+
60+ # Create backup in specified format
61+ backup_path = self ._create_backup (
62+ temp_clone_dir ,
63+ repo_backup_dir ,
64+ backup_name ,
65+ repository .backup_format
66+ )
67+
68+ # Clean up old backups based on retention policy
69+ self ._cleanup_old_backups (repo_backup_dir , repository .retention_count , repository .backup_format )
70+
71+ # Update backup job record
72+ backup_job .status = 'completed'
73+ backup_job .backup_path = str (backup_path )
74+ backup_job .file_size = self ._get_file_size (backup_path )
75+ backup_job .completed_at = datetime .utcnow ()
76+
77+ # Update repository last backup time
78+ repository .last_backup = datetime .utcnow ()
79+
80+ logger .info (f"Backup completed successfully: { backup_path } " )
8081
8182 except Exception as e :
8283 logger .error (f"Backup failed for repository { repository .name } : { str (e )} " )
@@ -85,6 +86,14 @@ def backup_repository(self, repository):
8586 backup_job .completed_at = datetime .utcnow ()
8687
8788 finally :
89+ # Always clean up temporary directory
90+ if temp_clone_dir and temp_clone_dir .exists ():
91+ try :
92+ logger .info (f"Cleaning up temporary directory: { temp_clone_dir } " )
93+ shutil .rmtree (temp_clone_dir )
94+ except Exception as cleanup_error :
95+ logger .error (f"Failed to cleanup temp directory { temp_clone_dir } : { cleanup_error } " )
96+
8897 db .session .commit ()
8998
9099 def _clone_repository (self , repository , clone_dir ):
@@ -97,9 +106,33 @@ def _clone_repository(self, repository, clone_dir):
97106 # Convert https://github.com/user/repo to https://[email protected] /user/repo 98107 clone_url = clone_url .replace ('https://github.com/' , f'https://{ repository .github_token } @github.com/' )
99108
100- # Clone the repository
101- git .Repo .clone_from (clone_url , clone_dir , depth = 1 )
102- logger .info (f"Repository cloned to: { clone_dir } " )
109+ # Clean up any existing temp directories for this repository first
110+ self ._cleanup_temp_directories (clone_dir .parent )
111+
112+ # Clone the repository with error handling
113+ try :
114+ git .Repo .clone_from (clone_url , clone_dir , depth = 1 )
115+ logger .info (f"Repository cloned to: { clone_dir } " )
116+ except git .GitCommandError as e :
117+ if "already exists and is not an empty directory" in str (e ):
118+ logger .warning (f"Directory exists, cleaning and retrying: { clone_dir } " )
119+ shutil .rmtree (clone_dir )
120+ clone_dir .mkdir (exist_ok = True )
121+ git .Repo .clone_from (clone_url , clone_dir , depth = 1 )
122+ else :
123+ raise e
124+
125+ def _cleanup_temp_directories (self , repo_backup_dir ):
126+ """Clean up old temporary directories that might be left behind"""
127+ try :
128+ temp_dirs = [d for d in repo_backup_dir .iterdir () if d .is_dir () and d .name .startswith ('temp_' )]
129+ for temp_dir in temp_dirs :
130+ # Remove temp directories older than 1 hour
131+ if datetime .utcnow ().timestamp () - temp_dir .stat ().st_mtime > 3600 :
132+ logger .info (f"Cleaning up old temp directory: { temp_dir } " )
133+ shutil .rmtree (temp_dir )
134+ except Exception as e :
135+ logger .warning (f"Failed to cleanup temp directories: { e } " )
103136
104137 def _create_backup (self , source_dir , backup_dir , backup_name , backup_format ):
105138 """Create backup in the specified format"""
0 commit comments