
    i-                         d Z ddlZddlZddlZddlmZ ddlmZmZ ddl	m
Z
mZ ddlmZ  ej                  e      Z G d d      Zy)	z?
Git operations manager for cloning and updating repositories.
    N)Path)OptionalTuple)RepoGitCommandError)InvalidGitRepositoryErrorc                       e Zd ZdZddefdZd ZdedefdZ	dd	ed
ededede
ee   ef   f
dZdedefdZdedee   fdZd	edefdZy)
GitManagerz:Manages Git operations for repository cloning and updates.	repos_dirc                 ~    t        |      | _        | j                  j                  dd       | j                          y)z
        Initialize Git manager.
        
        Args:
            repos_dir: Directory where repositories will be cloned
        T)parentsexist_okN)r   r   mkdir_configure_ssh_for_bitbucket)selfr   s     3/home/batmin/projects/sonar_scan/src/git_manager.py__init__zGitManager.__init__   s2     iTD9))+    c                 L   ddl }t        j                  j                  d      }t        j                  |d       t        j                  j                  d      }|j                         dk(  rd| d	}nd
| }|t        j                  d<   t        j                  d| d       y)z
        Configure SSH to handle Bitbucket host key verification.
        Sets GIT_SSH_COMMAND environment variable to accept Bitbucket's host key.
        r   Nz~/.sshT)r   z~/.ssh/known_hostsWindowsz?ssh -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=""z>ssh -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=GIT_SSH_COMMANDz+Configured SSH for Bitbucket (known_hosts: ))	platformospath
expandusermakedirssystemenvironloggerinfo)r   r   ssh_dirknown_hosts_pathssh_commands        r   r   z'GitManager._configure_ssh_for_bitbucket   s    
 	 ''$$X.
Gd+ 77--.BC
 ??	)[\l[mmnoK [[kZlmK )4

$%ABRASSTUVr   	repo_pathreturnc                    |j                         sy|dz  }|j                         r	 t        |      }|j                  }y	 t        |j                               }|st        j                  d| d       yt        j                  d| d	       y# t        t        t
        f$ r%}t        j                  d| d|        Y d}~yd}~ww xY w# t
        $ r%}t        j                  d
| d|        Y d}~yd}~ww xY w)a  
        Check if repository directory is empty or contains an invalid git repository.
        
        Args:
            repo_path: Path to repository directory
            
        Returns:
            True if directory is empty or contains invalid git repository
        T.gitFzRepository at z" appears to be invalid/corrupted: NzRepository directory z	 is emptyz! exists but has no .git directoryz&Error checking directory contents for : )existsr   remotesr   r   	Exceptionr!   warninglistiterdirr"   )r   r&   git_dirrepo_eitemss          r   _is_repo_empty_or_invalidz$GitManager._is_repo_empty_or_invalid:   s     ! f$>>ILL	**,-E3I;iHI 3I;>_`a .	J 	{:\]^\_`a   	NNCI;bQRPSTU	s5   B 4C 6C C	$CC		C:C55C:N	repo_slug	clone_urlusernamepasswordc                 ~   | j                   |z  }|}|rOd|v r0d|v r,|j                  dd      }t        |      dk(  r	|d   dz   }n|}n|}t        j	                  d|        nt        j                  d|        y	d
}		 | j                  |      r|j                         rGt        j	                  d| d       	 t        j                  |       t        j	                  d|        d}	t        j	                  d|        t        j                  ||      }t        j	                  d|        n	|j                         r|dz  j                         rt        j	                  d|        t        |      }	 |j                  d      }|j                  sGt        j                  d|        |j                   j#                  ddd       |j                  d      }|j%                          	 |j&                  j(                  }|j                   j+                          t        j	                  d| d| d       ||	fS # t        $ r%}
t        j                  d| d|
        Y d}
~
y	d}
~
ww xY w# t        $ rO}
t        j-                  d| d|
 d        |j%                          t        j	                  d!| d"       Y d}
~
d}
~
ww xY w# t.        $ rU t        j	                  d#|        |j1                  d|      }|j%                          t        j	                  d$|        Y w xY w# t2        $ r}
t5        |
      }t        j                  d%| d|
        d&|v sd'|v rYt        j                  d(| d)       t        j                  d*       t        j                  d+       t        j                  d,       nKd-|v sd.|v rCt        j                  d/| d)       t        j                  d0       t        j                  d,       Y d}
~
y	d}
~
wt        $ r%}
t        j                  d1| d|
        Y d}
~
y	d}
~
ww xY w)2aL  
        Clone repository if it doesn't exist, or update if it does.
        Uses SSH for cloning (SSH key must be set up).
        
        Args:
            repo_slug: Repository slug/name
            clone_url: Repository clone URL (SSH format: git@bitbucket.org:workspace/repo.git)
            username: Optional - not used for SSH (kept for backward compatibility)
            password: Optional - not used for SSH (kept for backward compatibility)
            
        Returns:
            Tuple of (Path to repository directory, is_first_clone), or (None, False) if failed
        @:      r   z:*****zUsing SSH clone URL: zNo clone URL provided for )NFFzRepository directory for z0 is empty or invalid, removing and cloning freshz,Removed invalid/empty repository directory: z.Failed to remove invalid repository directory r*   NTzCloning repository: z Successfully cloned repository: r)   zUpdating repository: origin)namezConfiguring refspec for z--addzremote.origin.fetchz#+refs/heads/*:refs/remotes/origin/*z!Successfully updated repository: z
 (branch: r   zCould not pull z+. Repository may be in detached HEAD state.zFetched changes for z (could not pull)zAdding origin remote for z*Successfully added remote and fetched for zGit operation failed for zPermission deniedzHost key verification failedzSSH authentication failed for z. Please verify:z,  - SSH key is set up and added to Bitbucketz:  - SSH key is in SSH agent or configured in ~/.ssh/configz)  - Repository exists and you have accesszAuthentication failedzfatal: unable to accesszAuthentication failed for z"  - SSH key is properly configuredz%Unexpected error handling repository )r   splitlenr!   r"   errorr6   r+   shutilrmtreer-   r   
clone_fromremoterefsdebuggitconfigfetchactive_branchrA   pullr.   
ValueErrorcreate_remoter   str)r   r7   r8   r9   r:   r&   authenticated_urlparts
masked_urlis_first_cloner4   r2   r@   current_branch	error_msgs                  r   clone_or_updatezGitManager.clone_or_updated   s    NNY.	 &  ''C3D,D)//Q7u:?!&qH!4J!2J.
KK/
|<=LL5i[ABH	--i8##%KK";I;Fv wx+i0&RS\R]$^_ "&29+>?'8)D>ykJK!!#V);(C(C(E3I;?@IZ![[h[7F ";;'?	{%KL1FHmn!%(!; LLNY)-););)@)@&G	{R\]k\llm$no n,,[ % +'UV_U``bcdbe%fg*+@ % Y2aSHs'tu&:9+EV$WXX	Y
 " ZKK";I; GH!//:KLFLLNKK"LYK XYZ  	AILL4YKr!EF #i/3QU^3^=i[HXYZKMY[HJ(I59RV_9_9)DTUVACHJ 	LL@2aSQR	s   ?:L+ :-H> 'BL+ 8A5K
 .AI/ :L+ >	I,I'"L+ 'I,,L+ /	K8AK=K
 KK
 
AL(%L+ 'L((L+ +	P<4CPP<P77P<c                 d    |dz  }|j                         }|st        j                  d|        |S )z
        Check if repository has sonar-project.properties file.
        
        Args:
            repo_path: Path to repository directory
            
        Returns:
            True if sonar-project.properties exists
        sonar-project.propertiesz&sonar-project.properties not found in )r+   r!   r.   )r   r&   sonar_propsr+   s       r   has_sonar_propertieszGitManager.has_sonar_properties   s9      "<<##%NNCI;OPr   c                 2    |dz  }|j                         r|S y)z
        Get path to sonar-project.properties file.
        
        Args:
            repo_path: Path to repository directory
            
        Returns:
            Path to sonar-project.properties, or None if not found
        r[   N)r+   )r   r&   r\   s      r   get_sonar_properties_pathz$GitManager.get_sonar_properties_path   s$      "<<r   c                    | j                   |z  }	 |j                         r.t        j                  |       t        j                  d|        y	 y# t        $ r%}t        j                  d| d|        Y d}~yd}~ww xY w)z
        Remove a cloned repository (optional cleanup).
        
        Args:
            repo_slug: Repository slug/name
            
        Returns:
            True if successfully removed
        zCleaned up repository: TzFailed to cleanup repository r*   NF)r   r+   rE   rF   r!   r"   r-   rD   )r   r7   r&   r4   s       r   cleanup_repozGitManager.cleanup_repo   s     NNY.		K!i(5i[AB "   	KLL82aSIJJ	Ks   =A 	A?A::A?)z./repos)NN)__name__
__module____qualname____doc__rR   r   r   r   boolr6   r   r   rY   r]   r_   ra    r   r   r
   r
      s    D	,# 	,W:(4 (D (Tn n n n^a nmrs{  }A  tB  DH  tH  nI n`d t $4 HTN c d r   r
   )re   r   loggingrE   pathlibr   typingr   r   rK   r   r   git.excr   	getLoggerrb   r!   r
   rg   r   r   <module>rm      s?    
    " % -			8	$x xr   