
                  	           S r SSKrSSKrSSKrSSKJrJr  SSKJr  SSK	J
r
  SSKJr  S rS rS	 rS
 rS\\\4   4S jr SS\\\4   S\S\\\4   4S jjrg)zWHelper functions to interact with git and github for remediation intents orchestration.    N)MappingTuple)const)run_subprocess)filesc            
          Sn [         R                  " U SS[        R                  " 5       [         R                  [         R                  SS9nSUR
                  R                  5       4$ ! [         R                   a     gf = f)zCheck whether the current directory is a git repo or not.

Returns:
  True, repo_root_path if the current directory is a git repo
  False, None otherwise.
zgit rev-parse --show-toplevelT)shellcheckcwdstdoutstderrtext)FN)
subprocessrunosgetcwdPIPEr   stripCalledProcessError)git_check_cmdresults     9lib/googlecloudsdk/api_lib/scc/remediation_intents/git.pyis_git_repor      sl    
4M^^$BIIKz	F $$&&&		&	& s   A&A) )B ?B c           	          [         R                  " SSSX/S[        R                  " 5       [         R                  [         R                  SS9n[        UR                  R                  5       5      $ )zHelper function to check if a branch exists in the remote.

Args:
  remote_name: Name of the remote of the repo at which to check.
  branch_name: Name of the branch to check.

Returns:
  Boolean indicating whether the branch exists in the remote.
gitz	ls-remotez--headsFT)r
   r   r   r   r   )r   r   r   r   r   boolr   r   )remote_namebranch_namer   s      r   branch_remote_existsr   /   sU     >>k9k?
))+____& 
fmm!!#	$$    c                    Sn[         R                  " / SQ5      R                  S5      nUR                  5        H  nX;   d  M
  UR	                  5       S   n  O   Uc  [
        R                  " 5       n[         R                  " SSSUSU/S	[        R                  " 5       [         R                  [         R                  S
9  [        X5      (       d8  [         R                  " SSSX/SU[         R                  [         R                  S
9  [         R                  " SS/SU[         R                  [         R                  S
9  U$ )aT  Returns the working tree directory for the branch.

   Will create a new working tree if one doesn't exist

Args:
  remote_name: Name of the remote of the repo at which to check.
  branch_name: Name of the branch for which the working tree directory is
    required.

Returns:
  Working tree directory path for the branch in string format.
N)r   worktreelistzutf-8r   r   r"   addz-BTr
   r   r   r   pushz--set-upstreamFpull)r   check_outputdecode
splitlinessplittempfilemkdtempr   r   r   r   r   )r   r   worktree_direxisting_worktreeslines        r   get_working_tree_dirr1   D   s    ,!..!
F7O  !++-dZZ\!_l	 .
 ##%LNN	
E<{C		z  99nn&*K
E< NN	z
 
r    c           	         [        X#S9nU R                  5        Hq  u  pV[        R                  R	                  XE5      n[
        R                  " Xv5        [        R                  " SSU/SU[        R                  [        R                  S9  Ms     [        R                  " SSSU/SU[        R                  [        R                  S9  [        R                  " SS	/SU[        R                  [        R                  S9  g
)a  Pushes the commit to the given branch with the given files data and commit message.

Args:
  files_data: Dictionary of file path (relative path of the files in original
    repo) and file data in string format to be written
  commit_message: Message to be added to the commit.
  remote_name: Name of the remote of the repo at which to check.
  branch_name: Name of the branch where commit needs to be pushed.
r   r   r   r$   Tr%   commitz-mFr&   N)
r1   itemsr   pathjoinr   WriteFileContentsr   r   r   )
files_datacommit_messager   r   r.   	file_path	file_dataabs_file_paths           r   push_commitr>   r   s     &, )..0iGGLL9M	M5NN	}% 1 ..hn-
____ ..fo
____r    returnc                    [        UUS9nSSSSUSUSU SUS	U/n [        R                  " US
U[        R                  [        R                  S9nUR                  R                  5       n	[        R                  " SSSSU/SU[        R                  [        R                  S9  S
U	4$ ! [        R                   a>  n
S[        R                  R                  U
R                  U
R                  S94s Sn
A
$ Sn
A
ff = f)a  Creates a PR for the given branch to the main base branch.

Args:
  title: PR title
  desc: PR description
  remote_name: Name of the remote of the repo at which to check.
  branch_name: The branch from which PR needs to be created.
  base_branch: The main branch name to be which PR needs to be merged.
  reviewers: List of reviewers to be added to the PR.

Returns:
  Boolean indicating whether the PR was created successfully or not.
  PR link if created successfully, otherwise error message.
r3   ghprcreatez--basez--headz--titlez--bodyz
--assigneeTr%   F)r   r   Nr   r"   removez--force)r1   r   r   r   r   r   r   r   PR_FAILURE_MSGformatr   )titledescr   r   base_branch	reviewersr.   
pr_commandppr_linkes              r   	create_prrO      s    " &,
 

*
P	A hhnnG ..j(I|<
____ 
w 
	&	& P%&&--QXXahh-OOOPs   AB& &C8:3C3-C83C8r9   firstc                     0 nSS/U(       a  S/O/ QSPSPSPn U R                  5        H3  u  pEX4/-   n[        R                  " U[        R                  SS9S	   X$'   M5     U$ ! [
        R                   a    0 s $ f = f)
a  Returns the first (creators) or last modifiers for the given files.

By default, it returns the last modifiers.

Args:
  files_data: Dictionary of file path and file contents.
  first: If True, returns the first modifiers for the files. Otherwise,
    returns the last modifiers for the files.

Returns:
  A dictionary of file path and the modifiers for the given files. If the
  command fails, an empty dictionary is returned. ["file_path" : "modifier"]
r   logz	--reversez-sz-n1z--pretty=format:%ae%nT)timeout_secstrip_outputr   )r5   r   GetOutputLinesr   TF_CMD_TIMEOUTr   r   )r9   rP   file_modifiersbase_cmdr;   _cmds          r   get_file_modifiersr[      s      .UB   +(
	"((*	{"c"0"?"?
5//d#	#n + 		&	& Is   AA# #A<;A<)F)__doc__r   r   r,   typingr   r   .googlecloudsdk.api_lib.scc.remediation_intentsr   googlecloudsdk.command_lib.coder   googlecloudsdk.core.utilr   r   r   r1   r>   r   strrO   r[    r    r   <module>rc      s    ^ 	   ! @ : *(%*+\'T7
497v 27S!*.S#Xr    