3
_Af'                @   s  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dl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mZmZmZ d dlmZmZmZm Z  d dlm!Z!m"Z" d dlm#Z# d dl$Z$d dl%Z%d d	l&m'Z'm(Z( d d
l)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1 e1 rNd dl2Z3n$d dl4Z4d dl5Z5e4j6dZ3e5e3_7e8Z9dd Z:dd Z;dd Z<dd Z=dd Z>da?dd Z@G dd deAZBG dd deAZCG dd deZDG dd  d eZEG d!d" d"eAZFd@d$d%ZGG d&d' d'eAZHG d(d) d)eAZIG d*d+ d+eAZJG d,d- d-eAZKG d.d/ d/eAZLG d0d1 d1eMZNG d2d3 d3eMZOG d4d5 d5eAZPG d6d7 d7eAZQG d8d9 d9eAZRG d:d; d;eZSG d<d= d=eAZTG d>d? d?eLZUdS )A    )print_functionN)Coloring)
GitCommandgit_require)	GitConfigIsIdGetSchemeFromUrlGetUrlCookieFileID_RE)GitError	HookErrorUploadErrorDownloadError)ManifestInvalidRevisionErrorManifestInvalidPathError)NoManifestException)IsTraceTrace)GitRefsHEADR_HEADSR_TAGSR_PUBR_M)
is_python3urllibc             C   s^   d|  }t |d}|j| W d Q R X ytj||  W n  tk
rX   tj|  Y nX d S )Nz%s.lockw)openwriteplatform_utilsrenameOSErrorremove)pathcontentlockfd r'   9/home/qytech/356xLinux510-101server/.repo/repo/project.py_lwrite:   s    
r)   c             G   s   | | }t d| tjd d S )Nz	error: %s)file)printsysstderr)fmtargsmsgr'   r'   r(   _errorG   s    r1   c             G   s   | | }t d| tjd d S )Nzwarn: %s)r*   )r+   r,   r-   )r.   r/   r0   r'   r'   r(   _warnL   s    r2   c             C   s   d|  S )N^r'   )rr'   r'   r(   not_revQ   s    r5   c             C   s   d| j dd d S )N'z''')replace)r4   r'   r'   r(   sqU   s    r8   c                  sL   t dkrHtjtjjtjjt tjj d  fddtj	 D a t S )aa  List the hooks present in the 'hooks' directory.

  These hooks are project hooks and are copied to the '.git/hooks' directory
  of all subprojects.

  This function caches the list of hooks (based on the contents of the
  'repo/hooks' directory) on the first call.

  Returns:
    A list of absolute paths to all of the files in the hooks directory.
  Nhooksc                s   g | ]}t jj |qS r'   )osr#   join).0x)dr'   r(   
<listcomp>l   s    z!_ProjectHooks.<locals>.<listcomp>)
_project_hook_listr   realpathr:   r#   abspathdirname__file__r;   listdirr'   r'   )r>   r(   _ProjectHooks\   s
    rF   c               @   s$   e Zd ZdZdd Zedd ZdS )DownloadedChangeNc             C   s"   || _ || _|| _|| _|| _d S )N)projectbase	change_idps_idcommit)selfrH   rI   rJ   rK   rL   r'   r'   r(   __init__s   s
    zDownloadedChange.__init__c          	   C   s6   | j d kr0| jjjdddddt| j| jd| _ | j S )Nz
--abbrev=8z--abbrev-commitz--pretty=onelinez	--reversez--date-orderz--)_commit_cacherH   bare_gitrev_listr5   rI   rL   )rM   r'   r'   r(   commitsz   s    

zDownloadedChange.commits)__name__
__module____qualname__rO   rN   propertyrR   r'   r'   r'   r(   rG   p   s   rG   c            
   @   s~   e Zd ZdZdZdd Zedd Zedd Zedd	 Z	ed
d Z
edd Zddf dddddddf
ddZdd ZdS )ReviewableBranchNc             C   s   || _ || _|| _d S )N)rH   branchrI   )rM   rH   rX   rI   r'   r'   r(   rN      s    zReviewableBranch.__init__c             C   s   | j jS )N)rX   name)rM   r'   r'   r(   rY      s    zReviewableBranch.namec             C   sh   | j d krbdddddt| jt| j df}y| jjj| | _ W n" tk
r`   | j	rV g | _ Y nX | j S )Nz
--abbrev=8z--abbrev-commitz--pretty=onelinez	--reversez--date-orderz--)
rO   r5   rI   r   rY   rH   rP   rQ   r   base_exists)rM   r/   r'   r'   r(   rR      s    
zReviewableBranch.commitsc             C   sB   t  }x6| jjjt| jt| j dD ]}|||dd < q&W |S )Nz--r      )dictrH   rP   rQ   r5   rI   r   rY   )rM   r4   rL   r'   r'   r(   unabbrev_commits   s    
z!ReviewableBranch.unabbrev_commitsc             C   s   | j jjdddt| j dS )Nz--pretty=format:%cdz-n1z--)rH   rP   logr   rY   )rM   r'   r'   r(   date   s    
zReviewableBranch.datec             C   sL   | j dkrFy | jjjdt| j d| _ W n tk
rD   d| _ Y nX | j S )zxWhether the branch we're tracking exists.

    Normally it should, but sometimes branches we track can get deleted.
    Nz--verifyTF)_base_existsrH   rP   	rev_parser5   rI   r   )rM   r'   r'   r(   rZ      s    

zReviewableBranch.base_existsFTc             C   s*   | j j| j|||||||||	|
|d d S )N)rX   peopledryrun
auto_topichashtagsdraftprivatenotifywipdest_branchvalidate_certspush_options)rH   UploadForReviewrY   )rM   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   r'   r'   r(   rn      s    
z ReviewableBranch.UploadForReviewc             C   sh   i }| j jj| jjj| j jd}x@|jdD ]2}y|j \}}|||< W q. tk
r^   Y q.X q.W |S )Nzrefs/changes/*
)	rH   rP   Z	ls_remoterX   remoteZSshReviewUrl	UserEmailsplit
ValueError)rM   refsoutputlineZsharefr'   r'   r(   GetPublishedRefs   s    
z!ReviewableBranch.GetPublishedRefs)rS   rT   rU   rO   ra   rN   rV   rY   rR   r]   r`   rZ   rn   rx   r'   r'   r'   r(   rW      s&   	rW   c               @   s   e Zd Zdd ZdS )StatusColoringc             C   s   t j| |d | jddd| _| jddd| _| jddd| _| jddd| _| jd	d
d| _| jddd| _| jddd| _	d S )Nstatusheaderbold)attrnobranchred)fg	importantaddedgreenchanged	untracked)
r   rN   printerrH   rX   r~   r   r   r   r   )rM   configr'   r'   r(   rN      s    zStatusColoring.__init__N)rS   rT   rU   rN   r'   r'   r'   r(   ry      s   ry   c               @   s   e Zd Zdd ZdS )DiffColoringc             C   s2   t j| |d | jddd| _| jddd| _d S )Ndiffr{   r|   )r}   failr   )r   )r   rN   r   rH   r   )rM   r   r'   r'   r(   rN      s    zDiffColoring.__init__N)rS   rT   rU   rN   r'   r'   r'   r(   r      s   r   c               @   s   e Zd Zdd ZdS )_Annotationc             C   s   || _ || _|| _d S )N)rY   valuekeep)rM   rY   r   r   r'   r'   r(   rN     s    z_Annotation.__init__N)rS   rT   rU   rN   r'   r'   r'   r(   r     s   r   Fc             C   s   t jdt jtjj }|j|}|r.|j }| }x~|D ]v}|dkrTtd||f tjj	||}t
j|rztd|f tjj|r8tjj| r8t
j| r8td|f q8W |rtjj	||}|S )aX  Make sure |subpath| is completely safe under |base|.

  We make sure no intermediate symlinks are traversed, and that the final path
  is not a special file (e.g. not a socket or fifo).

  NB: We rely on a number of paths already being filtered out while parsing the
  manifest.  See the validation logic in manifest_xml.py for more details.
  z[/%s]...z%s: "%s" not allowed in pathsz!%s: traversing symlinks not allowz,%s: only regular files & directories allowed>   r   r   )recompileescaper:   r#   seprr   popr   r;   r   islinkexistsisfileisdir)rI   subpath	skipfinalZresep
componentsZ	finalpartr#   partr'   r'   r(   _SafeExpandPath  s(    


r   c               @   s    e Zd ZdZdd Zdd ZdS )	_CopyFilez*Container for <copyfile> manifest element.c             C   s   || _ || _|| _|| _dS )a+  Register a <copyfile> request.

    Args:
      git_worktree: Absolute path to the git project checkout.
      src: Relative path under |git_worktree| of file to read.
      topdir: Absolute path to the top of the repo client checkout.
      dest: Relative path under |topdir| of file to write.
    N)git_worktreetopdirsrcdest)rM   r   r   r   r   r'   r'   r(   rN   9  s    	z_CopyFile.__init__c             C   s  t | j| j}t | j| j}tj|r6td| jf tj|rPtd| jf tj	j
| sntj|| ry|tj	j
|rtj| n tj	j|}tj|stj| tj|| tj|tj }|tjtjB tjB  @ }tj|| W n" tk
r   td|| Y nX d S )Nz(%s: copying from directory not supportedz$%s: copying to directory not allowedzCannot copy file %s to %s)r   r   r   r   r   r   r   r   r:   r#   r   filecmpcmpr"   rC   makedirsshutilcopystatST_MODES_IWUSRS_IWGRPS_IWOTHchmodIOErrorr1   )rM   r   r   dest_dirmoder'   r'   r(   _CopyG  s*    



z_CopyFile._CopyN)rS   rT   rU   __doc__rN   r   r'   r'   r'   r(   r   6  s   r   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )		_LinkFilez*Container for <linkfile> manifest element.c             C   s   || _ || _|| _|| _dS )a4  Register a <linkfile> request.

    Args:
      git_worktree: Absolute path to the git project checkout.
      src: Target of symlink relative to path under |git_worktree|.
      topdir: Absolute path to the top of the repo client checkout.
      dest: Relative path under |topdir| of symlink to create.
    N)r   r   r   r   )rM   r   r   r   r   r'   r'   r(   rN   h  s    	z_LinkFile.__init__c             C   s   t j| st j||kryHtjj|r4t j| n tjj|}t j|sTtj	| t j
|| W n  tk
r   td|| Y nX d S )NzCannot link file %s to %s)r   r   readlinkr:   r#   lexistsr"   rC   r   r   symlinkr   r1   )rM   relSrcabsDestr   r'   r'   r(   Z__linkItv  s    

z_LinkFile.__linkItc       
      C   s   | j dkr| j}nt| j| j }tjj|rbt| j| jdd}tjj|tjj	|}| j
|| nt| j| j}tjj|rtj| rtd| nbx`tj|D ]R}tjj	|}tjj||}tjj|}tjj||}tjj||}	| j
|	| qW dS )zLink the self.src & self.dest paths.

    Handles wild cards on the src linking all of the files in the source in to
    the destination directory.
    r   T)r   z5Link error: src with wildcard, %s must be a directoryN)r   r   r   r:   r#   r   r   r   relpathrC   _LinkFile__linkItr   r   r1   globbasenamer;   )
rM   r   r   r   Z
absSrcFileZ	absSrcDirZ	relSrcDirZsrcFiler   r   r'   r'   r(   _Link  s"    
z_LinkFile._LinkN)rS   rT   rU   r   rN   r   r   r'   r'   r'   r(   r   e  s   r   c               @   s   e Zd ZdddZdS )
RemoteSpecNc             C   s.   || _ || _|| _|| _|| _|| _|| _d S )N)rY   urlpushUrlreviewrevision	orig_namefetchUrl)rM   rY   r   r   r   r   r   r   r'   r'   r(   rN     s    zRemoteSpec.__init__)NNNNNN)rS   rT   rU   rN   r'   r'   r'   r(   r     s        r   c               @   s~   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zedd Zdd Zdd Zdd Zdd ZdS )RepoHooka1  A RepoHook contains information about a script to run as a hook.

  Hooks are used to run a python script before running an upload (for instance,
  to run presubmit checks).  Eventually, we may have hooks for other actions.

  This shouldn't be confused with files in the 'repo/hooks' directory.  Those
  files are copied into each '.git/hooks' folder for each project.  Repo-level
  hooks are associated instead with repo actions.

  Hooks are always python.  When a hook is run, we will load the hook into the
  interpreter and execute its main() function.
  Fc             C   sJ   || _ || _|| _|| _|| _| jr@tjj| jj| j d | _	nd| _	dS )a  RepoHook constructor.

    Params:
      hook_type: A string representing the type of hook.  This is also used
          to figure out the name of the file containing the hook.  For
          example: 'pre-upload'.
      hooks_project: The project containing the repo hooks.  If you have a
          manifest, this is manifest.repo_hooks_project.  OK if this is None,
          which will make the hook a no-op.
      topdir: Repo's top directory (the one containing the .repo directory).
          Scripts will run with CWD as this directory.  If you have a manifest,
          this is manifest.topdir
      manifest_url: The URL to the manifest git repo.
      abort_if_user_denies: If True, we'll throw a HookError() if the user
          doesn't allow us to run the hook.
    z.pyN)

_hook_type_hooks_project_manifest_url_topdir_abort_if_user_deniesr:   r#   r;   worktree_script_fullpath)rM   Z	hook_typeZhooks_projectr   Zmanifest_urlZabort_if_user_deniesr'   r'   r(   rN     s    zRepoHook.__init__c             C   s   | j std| j jjdS )aH  Return a hash of the contents of the hooks directory.

    We'll just use git to do this.  This hash has the property that if anything
    changes in the directory we will return a different has.

    SECURITY CONSIDERATION:
      This hash only represents the contents of files in the hook directory, not
      any other files imported or called by hooks.  Changes to imported files
      can change the script behavior without affecting the hash.

    Returns:
      A string representing the hash.  This will always be ASCII so that it can
      be printed to the user easily.
    z(Must have hooks to calculate their hash.r   )r   AssertionErrorwork_gitrb   )rM   r'   r'   r(   _GetHash  s    zRepoHook._GetHashc             C   s   | j r
dS dS dS )z7Return 'must' if the hook is required; 'should' if not.ZmustZshouldN)r   )rM   r'   r'   r(   _GetMustVerb  s    zRepoHook._GetMustVerbc             C   s   | j  r| j S | j S dS )a  Check to see whether this hook has been approved.

    We'll accept approval of manifest URLs if they're using secure transports.
    This way the user can say they trust the manifest hoster.  For insecure
    hosts, we fall back to checking the hash of the hooks repo.

    Note that we ask permission for each individual hook even though we use
    the hash of all hooks when detecting changes.  We'd like the user to be
    able to approve / deny each hook individually.  We only use the hash of all
    hooks because there is no other easy way to detect changes to local imports.

    Returns:
      True if this hook is approved to run; False otherwise.

    Raises:
      HookError: Raised if the user doesn't approve and abort_if_user_denies
          was passed to the consturctor.
    N)_ManifestUrlHasSecureScheme_CheckForHookApprovalManifest_CheckForHookApprovalHash)rM   r'   r'   r(   _CheckForHookApproval  s    zRepoHook._CheckForHookApprovalc       
      C   s   | j j}d| j|f }|j|}|dk	r@||kr4dS d|f }nd}tjj r||d 7 }t|j }	t	  |	dkrxdS |	d	kr|j
|| dS | jrtd
| j dS )a[  Check for approval for a particular attribute and hook.

    Args:
      subkey: The git config key under [repo.hooks.<hook_type>] to store the
          last approved string.
      new_val: The new value to compare against the last approved one.
      main_prompt: Message to display to the user to ask for approval.
      changed_prompt: Message explaining why we're re-asking for approval.

    Returns:
      True if this hook is approved to run; False otherwise.

    Raises:
      HookError: Raised if the user doesn't approve and abort_if_user_denies
          was passed to the consturctor.
    zrepo.hooks.%s.%sNTzWARNING: %s

 z (yes/always/NO)? yyesalwaysz.You must allow the %s hook or use --no-verify.F)r   r   )r   r   r   	GetStringr,   stdoutisattyinputlowerr+   	SetStringr   r   )
rM   Zsubkeynew_valZmain_promptZchanged_promptZhooks_configZgit_approval_keyZold_valpromptresponser'   r'   r(   _CheckForHookApprovalHelper.  s*    


z$RepoHook._CheckForHookApprovalHelperc             C   s   d}t jj| j}|j|kS )z8Check if the URI for the manifest is a secure transport.r*   httpssshpersistent-httpsssorpc)r*   r   r   r   r   r   )r   parseurlparser   scheme)rM   Zsecure_schemesZparse_resultsr'   r'   r(   r   f  s    z$RepoHook._ManifestUrlHasSecureSchemec             C   s"   | j d| jd| jf d| jf S )zCheck whether the user has approved this manifest host.

    Returns:
      True if this hook is approved to run; False otherwise.
    ZapprovedmanifestzRun hook scripts from %sz.Manifest URL has changed since %s was allowed.)r   r   r   )rM   r'   r'   r(   r   l  s
    
z&RepoHook._CheckForHookApprovalManifestc             C   s.   d}| j d| j || j | jf d| jf S )zCheck whether the user has approved the hooks repo.

    Returns:
      True if this hook is approved to run; False otherwise.
    zERepo %s run the script:
  %s

Do you want to allow this script to runZapprovedhashz*Scripts have changed since %s was allowed.)r   r   r   r   r   )rM   r   r'   r'   r(   r   x  s    z"RepoHook._CheckForHookApprovalHashc             C   s`   | j  dd }|sdS |d j }tjd|}|s8dS |jd}tjj|dkr\|jd}|S )a5  Extract the interpreter used in the shebang.

    Try to locate the interpreter the script is using (ignoring `env`).

    Args:
      data: The file content of the script.

    Returns:
      The basename of the main script interpreter, or None if a shebang is not
      used or could not be parsed out.
    N   r   z^#!\s*([^\s]+)(?:\s+([^\s]+))?env   )
splitlinesstripr   matchgroupr:   r#   r   )data	firstlineZshebangminterpr'   r'   r(   _ExtractInterpFromShebang  s    

z"RepoHook._ExtractInterpFromShebangc             K   sd   d| j tj|tj|d }|ddg}tj|tjd}|j|jdd |jr`t	d| j
f d	S )
ae  Execute the hook script through |interp|.

    Note: Support for this feature should be dropped ~Jun 2021.

    Args:
      interp: The Python program to run.
      context: Basic Python context to execute the hook inside.
      kwargs: Arbitrary arguments to pass to the hook script.

    Raises:
      HookError: When the hooks failed for any reason.
    a  
import json, os, sys
path = '''%(path)s'''
kwargs = json.loads('''%(kwargs)s''')
context = json.loads('''%(context)s''')
sys.path.insert(0, os.path.dirname(path))
data = open(path).read()
exec(compile(data, path, 'exec'), context)
context['main'](**kwargs)
)r#   kwargscontextz-cz"import sys; exec(sys.stdin.read()))stdinzutf-8)r   zFailed to run %s hook.N)r   jsondumps
subprocessPopenPIPEcommunicateencode
returncoder   r   )rM   r   r   r   Zscriptcmdprocr'   r'   r(   _ExecuteHookViaReexec  s    
zRepoHook._ExecuteHookViaReexecc             K   s   yt t|| jd| W n* tk
rB   tdtj | jf Y nX d|krZtd| j y|d f | W n* tk
r   tdtj | jf Y nX dS )a(  Execute the hook code in |data| directly.

    Args:
      data: The code of the hook to execute.
      context: Basic Python context to execute the hook inside.
      kwargs: Arbitrary arguments to pass to the hook script.

    Raises:
      HookError: When the hooks failed for any reason.
    execz1%s
Failed to import %s hook; see traceback above.mainzMissing main() in: "%s"z9%s
Failed to run main() for %s hook; see traceback above.N)r  r   r   	Exceptionr   	traceback
format_excr   )rM   r   r   r   r'   r'   r(   _ExecuteHookViaImport  s    zRepoHook._ExecuteHookViaImportc       
      K   s>  t j }tj}zt j| j t jj| jgtjdd  t_d| ji}|j }d|d< t	| jj
 }| j|}d}|rt jj|}|jdrtjjdkrd}n|jd	rtjjdkrd}|ry| j||f| W n8 tk
r }	 z|	jtjkrd}n W Y dd}	~	X nX |s$| j||f| W d|t_t j| X dS )
a+  Actually execute the given hook.

    This will run the hook's 'main' function in our python interpreter.

    Args:
      kwargs: Keyword arguments to pass to the hook.  These are often specific
          to the hook type.  For instance, pre-upload hooks will contain
          a project_list.
    r   NrD   TZhook_should_take_kwargsFZpython2r   python3)r:   getcwdr,   r#   chdirr   rC   r   r   r   readr   r   
startswithversion_infomajorr  r!   errnoENOENTr
  )
rM   r   Z	orig_pathZorig_syspathr   r   r   Zreexecproger'   r'   r(   _ExecuteHook  s8     
	
zRepoHook._ExecuteHookc             K   sZ   | j  s| j| j jkrdS tjj| js6td| j | rJ| j  rJdS | j	f | dS )as  Run the hook.

    If the hook doesn't exist (because there is no hooks project or because
    this particular hook is not enabled), this is a no-op.

    Args:
      user_allows_all_hooks: If True, we will never prompt about running the
          hook--we'll just assume it's OK to run it.
      kwargs: Keyword arguments to pass to the hook.  These are often specific
          to the hook type.  For instance, pre-upload hooks will contain
          a project_list.

    Raises:
      HookError: If there was a problem finding the hook or the user declined
          to run a required hook (from _CheckForHookApproval).
    NzCouldn't find repo hook: "%s")
r   r   enabled_repo_hooksr:   r#   r   r   r   r   r  )rM   Zuser_allows_all_hooksr   r'   r'   r(   Run.  s    
zRepoHook.RunN)F)rS   rT   rU   r   rN   r   r   r   r   r   r   r   staticmethodr   r  r
  r  r  r'   r'   r'   r(   r     s   
8% Cr   c               @   s  e Zd ZddgZddddgZddd	gZd
dgZdddZedd Z	edd Z
edd Zdd ZdddZdZdZedd Zedd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zdd)d*Zd+d, Zdd-d.Zdd/d0Zdd1d2Zdd3d4Zdd5d6Zd7d8 Zdg g fddf dddddddfd9d:Zdd;d<Z dd=d>Z!d?d@ Z"dAdB Z#dCdD Z$ddEdFZ%ddGdHZ&dIdJ Z'dKdL Z(dMdN Z)dOdP Z*ddQdRZ+ddTdUZ,dVdW Z-dXdY Z.dZd[ Z/d\d] Z0d^d_ Z1d`da Z2ddddeZ3dfdg Z4ddhdiZ5ddjdkZ6ddldmZ7dndo Z8dpdq Z9ddrdsZ:dtdu Z;dvdw Z<dxdy Z=ddzd{Z>dd|d}Z?dd~dZ@dddZAdddZBdddZCdddZDdd ZEdd ZFdd ZGdd ZHdd ZIdd ZJdd ZKdddZLdd ZMdd ZNdd ZOedd ZPdddZQdddZRG dd deSZTdS )Projectdescriptioninfor9   objectszrr-cachesvnr   zpacked-refsshallowlogsrt   TNFc             C   sZ  || _ || _|| _|jdd| _|jdd| _|rJtjj|jdd| _	nd| _	|| _
|| _|	dkrx|rxt|rx|| _n|	| _|
| _|| _|| _|| _|| _|| _|| _|| _|| _|| _|| _g | _i | _g | _g | _g | _tj| j| j j d| _!| j	r| j"| d|d| _#nd| _#| j"| d|d| _$t%|| _&| j"| d|d| _'|| _(|| _)g | _*dS )a,  Init a Project object.

    Args:
      manifest: The XmlManifest object.
      name: The `name` attribute of manifest.xml's project element.
      remote: RemoteSpec object specifying its remote's properties.
      gitdir: Absolute path of git directory.
      objdir: Absolute path of directory to store git objects.
      worktree: Absolute path of git working tree.
      relpath: Relative path of git working tree to repo's top directory.
      revisionExpr: The `revision` attribute of manifest.xml's project element.
      revisionId: git commit id for checking out.
      rebase: The `rebase` attribute of manifest.xml's project element.
      groups: The `groups` attribute of manifest.xml's project element.
      sync_c: The `sync-c` attribute of manifest.xml's project element.
      sync_s: The `sync-s` attribute of manifest.xml's project element.
      sync_tags: The `sync-tags` attribute of manifest.xml's project element.
      upstream: The `upstream` attribute of manifest.xml's project element.
      parent: The parent Project object.
      use_git_worktrees: Whether to use `git worktree` for this project.
      is_derived: False if the project was explicitly defined in the manifest;
                  True if the project is a discovered submodule.
      dest_branch: The branch to which to push changes for review by default.
      optimized_fetch: If True, when a project is set to a sha1 revision, only
                       fetch from the remote if the sha1 is not present locally.
      old_revision: saved git commit id for open GITC projects.
    \/N)gitdirdefaultsF)barer#  T)+manifestrY   rp   r7   r#  objdirr:   r#   normpathr   r   revisionExprr   
revisionIdrebasegroupssync_csync_s	sync_tagsclone_depthupstreamparentuse_git_worktrees
is_derivedoptimized_fetchsubprojectsZ	snapshots	copyfiles	linkfilesannotationsr   ForRepositoryglobalConfigr   _GitGetByExecr   rP   r   bare_refbare_objdirrk   old_revisionr  )rM   r&  rY   rp   r#  r'  r   r   r)  r*  r+  r,  r-  r.  r/  r0  r1  r2  r3  r4  rk   r5  r?  r'   r'   r(   rN   X  sT    2
zProject.__init__c             C   s   | j S )N)r4  )rM   r'   r'   r(   Derived  s    zProject.Derivedc             C   s   t j| jot j| jS )N)r   r   r#  r'  )rM   r'   r'   r(   Exists  s    zProject.Existsc             C   sB   y| j j }W n tk
r"   dS X |jtr>|ttd S dS )zObtain the name of the currently checked out branch.

    The branch name omits the 'refs/heads/' prefix.
    None is returned if the project is on a detached HEAD, or if the work_git is
    otheriwse inaccessible (e.g. an incomplete sync).
    N)r   GetHeadr   r  r   len)rM   br'   r'   r(   CurrentBranch  s    
zProject.CurrentBranchc             C   s@   t jj| jjdp>t jj| jjdp>t jjt jj| jdS )Nzrebase-applyzrebase-mergez.dotest)r:   r#   r   r   GetDotgitPathr;   r   )rM   r'   r'   r(   IsRebaseInProgress  s    zProject.IsRebaseInProgressc             C   sN   | j jdddd | j jdddtr(dS | j jd	r8dS |rJ| j j rJdS d
S )z3Is the working directory modified in some way?
    z-qz
--unmergedz--ignore-missingz	--refreshz
diff-indexz-Mz--cachedTz
diff-filesF)r   update_indexDiffZr   LsOthers)rM   consider_untrackedr'   r'   r(   IsDirty  s    zProject.IsDirtyc             C   s   | j dkr| j  | j S )z%Obtain the user's personal name.
    N)_userident_name_LoadUserIdentity)rM   r'   r'   r(   UserName  s    
zProject.UserNamec             C   s   | j dkr| j  | j S )z[Obtain the user's email address.  This is very likely
       to be their Gerrit login.
    N)_userident_emailrN  )rM   r'   r'   r(   rq     s    
zProject.UserEmailc             C   sJ   | j jd}tjdj|}|r:|jd| _|jd| _nd| _d| _d S )NZGIT_COMMITTER_IDENTz^(.*) <([^>]*)> r   r   r   )rP   varr   r   r   r   rM  rP  )rM   ur   r'   r'   r(   rN    s    zProject._LoadUserIdentityc             C   s   | j j|S )z/Get the configuration for a single remote.
    )r   	GetRemote)rM   rY   r'   r'   r(   rS    s    zProject.GetRemotec             C   s   | j j|S )z/Get the configuration for a single branch.
    )r   	GetBranch)rM   rY   r'   r'   r(   rT    s    zProject.GetBranchc             C   s   | j }| j}i }xV|j D ]J\}}|jtr|ttd }| j|}||k|_d|_||_	|||< qW xB|j D ]6\}}|jt
rr|tt
d }|j|}|rr||_qrW |S )z%Get all existing local branches.
    N)rE  _allrefsitemsr  r   rC  rT  currentZ	publishedr   r   get)rM   rW  all_refsheadsrY   ref_idrD  r'   r'   r(   GetBranches  s$    





zProject.GetBranchesc             C   sn   |pdg}dg| j pg  }d|kr,|dg7 }d}x8|D ]0}|jdrZ|dd |krZd}q6||kr6d}q6W |S )	a'  Returns true if the manifest groups specified at init should cause
       this project to be synced.
       Prefixing a manifest group with "-" inverts the meaning of a group.
       All projects are implicitly labelled with "all".

       labels are resolved in order.  In the example case of
       project_groups: "all,group1,group2"
       manifest_groups: "-group1,group2"
       the project will be matched.

       The special manifest group "default" will match any project that
       does not have the special project group "notdefault"
    defaultallZ
notdefaultF-r   NT)r,  r  )rM   Zmanifest_groupsZexpanded_manifest_groupsZexpanded_project_groupsZmatchedr   r'   r'   r(   MatchesGroups1  s    


zProject.MatchesGroupsc             C   s   g }| j jdddd | j r0|jd |s0|S | j jddtj }|rZ|j| |sZ|S | j jdj }|r|j| |s|S | j j }|r|j| |S )	a  Returns a list of strings, uncommitted files in the git tree.

    Args:
      get_all: a boolean, if True - get information about all different
               uncommitted files. If False - return as soon as any kind of
               uncommitted files is detected.
    z-qz
--unmergedz--ignore-missingz	--refreshzrebase in progressz
diff-indexz--cachedz
diff-files)	r   rH  rG  appendrI  r   keysextendrJ  )rM   get_alldetailsZchangesr'   r'   r(   UncommitedFilesN  s.    




zProject.UncommitedFilesc             C   s   | j ddrdS dS dS )z3Returns true if there are uncommitted changes.
    F)rd  TN)rf  )rM   r'   r'   r(   
HasChangesr  s    zProject.HasChangesc             C   s  t j| jsF|dkrtj}t|d td| j |d td|d dS | jjdddd | j	 }| jj
d	d
dt}| jj
d}| jj }| r| r| r| r| j rdS t| j}|dk	r|j| |jd| jd  |r|j  dS | j}|dkr|jd n|jd| |j  |r2|jd |j  t }	|	j|j  |	j|j  |	j| x>tt|	D ],}
y||
 }W n tk
r   d}Y nX y||
 }W n tk
r   d}Y nX |r|jj }nd}|r|jj }nd}|r|jrd|||j|
|j f }nd|||
f }|r@| r@|j!d| nR|rL|sZ| rh|rh|j"d| n*| r| r|j#d| n|j$d| |j  qnW dS )zPrints the status of the repository to stdout.

    Args:
      output_redir: If specified, redirect the output to this object.
      quiet:  If True then only print the project name.  Do not print
              the modified files, branch name, etc.
    N)r*   zproject %s/z  missing (run "repo sync")z-qz
--unmergedz--ignore-missingz	--refreshz
diff-indexz-Mz--cachedz
diff-filesZCLEANzproject %-40sz/ ZDIRTYz(*** NO BRANCH ***)z	branch %sz+prior sync failed; rebase still in progressr_  z %s%s	%s => %s (%s%%)z %s%s	%sz%s)%r   r   r   r,   r   r+   r   r   rH  rG  rI  r   rJ  rE  ry   r   redirectrH   nlr~   rX   r   listrc  rb  sortedsetKeyErrorrz   upperr   src_pathlevelr   r   r   r   )rM   Zoutput_redirquietrbZdidfZdooutrX   pathspifZi_statusZf_statusrv   r'   r'   r(   PrintWorkTreeStatusz  s    

 






zProject.PrintWorkTreeStatusc             C   s4  t | j}dg}|jr |jd |jt |rN|jd| j  |jd| j  |jd yt| |ddd}W nX tk
r } z<|j  |j	d| j  |j  |j
d	t| |j  d
S d}~X nX d
}x\|jjD ]P}t|ds|j }|s|j  |j	d| j  |j  d}t|dd  qW |j dkS )z3Prints the status of the repository to stdout.
    r   z--colorz--src-prefix=a/%s/z--dst-prefix=b/%s/z--T)capture_stdoutcapture_stderrzproject %s/z%sFNr   r   r   )r   r   is_onra  r   r   r   r   ri  rH   r   strprocessr   hasattrdecoder+   Wait)rM   Zabsolute_pathsrt  r  rv  r  Zhas_diffrv   r'   r'   r(   PrintWorkTreeDiff  s@    




zProject.PrintWorkTreeDiffc             C   sV   t | }|dkr4y| jj|S  tk
r0   dS X ny|| S  tk
rP   dS X dS )zWas the branch published (uploaded) for code review?
       If so, returns the SHA-1 hash of the last published
       state for the branch.
    N)r   rP   rb   r   rm  )rM   rX   rY  keyr'   r'   r(   WasPublished  s    zProject.WasPublishedc             C   s   |dkr| j }t }i }x<|j D ]0\}}|jtr@|j| q"|jtr"|||< q"W x>|j D ]2\}}|ttd }t| |kr`| jj	|| q`W dS )z%Prunes any stale published refs.
    N)
rU  rl  rV  r  r   addr   rC  rP   	DeleteRef)rM   rY  rZ  ZcanrmrY   r[  nr'   r'   r(   CleanPublishedCache  s    

zProject.CleanPublishedCachec       	      C   s   i }i }xT| j j D ]F\}}|jtr<|||ttd < q|jtr|||ttd < qW g }xP|j D ]D\}}||kr|| |krql|r||krql| j|}|rl|j| qlW |S )z8List any branches which can be uploaded for review.
    N)rU  rV  r  r   rC  r   GetUploadableBranchra  )	rM   Zselected_branchrZ  ZpubedrY   r[  readyrX   rr  r'   r'   r(   GetUploadableBranches  s"    


zProject.GetUploadableBranchesc             C   s0   | j |}|j}|jr,t| ||}|jr,|S dS )z-Get a single uploadable branch, or None.
    N)rT  
LocalMergerW   rR   )rM   Zbranch_namerX   rI   rr  r'   r'   r(   r  5  s    
zProject.GetUploadableBranchc             C   sT  |dkr| j }|dkrtd| j|}|js<td|j |jjsTtd|jj |
dkrb| j}
|
dkrp|j}
|
j	t
st
|
 }
|jjs| j|j_|jj  |jj| j|}|dkrtddg}|r|jd |j	dr|jd	 x$|pg D ]}|jd
 |j| qW |j| |
j	t
r2|
tt
d }
d}|r@d}dt
|j ||
f }g }|rn|d|j g7 }|dd |D 7 }|dd |d D 7 }|dd |d D 7 }|r|d| g7 }|r|dg7 }|	r|dg7 }|r|d dj| }|j| t| |ddj dkr"tdd|jj|
f }| jjt|j t
|j |d dS )z.Uploads the named branch for code review.
    Nznot currently on a branchz!branch %s does not track a remotezremote %s has no review urlzreview not configuredpushz-nzssh://z"--receive-pack=gerrit receive-packz-oforZdraftsz%s:refs/%s/%sztopic=c             S   s   g | ]}d | qS )zt=%sr'   )r<   rv  r'   r'   r(   r?     s    z+Project.UploadForReview.<locals>.<listcomp>c             S   s   g | ]}d | qS )zr=%sr'   )r<   rv  r'   r'   r(   r?     s    r   c             S   s   g | ]}d | qS )zcc=%sr'   )r<   rv  r'   r'   r(   r?     s    r   znotify=rh   rj   %,T)r%  zUpload failedzposted to %s for %s)message)rE  r   rT  r  rY   rp   r   rk   merger  r   projectnameSave	ReviewUrlrq   r   ra  rC  r;   r   r  rP   	UpdateRefr   )rM   rX   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   r   r  Zpush_optionZupload_typeZref_specoptsr0   r'   r'   r(   rn   @  st    











zProject.UploadForReviewc             C   sf   y(t j|d}|j|d dS Q R X W n8 tt jfk
r` } ztd|t| W Y dd}~X nX dS )zqExtract the given tar on its current location

    Args:
        - tarpath: The path to the actual tar file

    r4   )r#   TNzCannot extract archive %s: %sF)tarfiler   
extractallr   TarErrorr1   r~  )rM   tarpathr#   tarr  r'   r'   r(   _ExtractArchive  s    "zProject._ExtractArchivec          6   C   s0  |ot | t r| jjjdr0td| j dS | jjdd}|jdd}d| }| j	j
}y| j||d	 W n* tk
r } ztd
| dS d}~X nX tjj||}| j||dsdS ytj| W n4 tk
 r } ztd|t| W Y dd}~X nX | j  dS |dkr| j }|r0| j||d n| j|d | j  |rtjj| jd}y2t| }tjj| jd|j j }W dQ R X W n t k
r   d}Y nX nd}|r|dkr| j!|||drd}|s| j"rd}n | j	j#sd}n| j	j$j"rd}| j%sd}| j&r$| j&}n| j	j'j(j)d}|	oNt*j+| j,oN| j- sx| j.|||||||
||||dsxdS | j	j'}|j(j/d}|rtjj| jd}tjj0|rdddg}t1| |ddj2 dkrdS tj| | j3r| j4  n:| j5  ytjtjj| jd W n tk
r*   Y nX dS )zzPerform only the network IO portion of the sync process.
       Local working directory/branch state is not affected.
    http://https://z2%s: Cannot fetch archives from http/https remotes.Fr!  r"  _z%s.tar)cwdz%sN)r#   zCannot remove archive %s: %sT)
force_syncrq  )rq  zobjects/info/alternatesr  )initialrq  verbosez
repo.depth)r  rq  r  alt_dircurrent_branch_onlytagsprunedepth
submodulesr  clone_filterzrepo.dissociateZrepackz-az-d)r%  r   
FETCH_HEAD)r  r  )6
isinstanceMetaProjectrp   r   r  r1   rY   r   r7   r&  r   _FetchArchiver   r:   r#   r;   r  r   r"   r!   r2   r~  _CopyAndLinkFilesrA  _InitGitDir_UpdateHooks_InitRemoter#  r   r'  readlinerstripr   _ApplyCloneBundler-  Z_loadedr]  r/  r0  manifestProjectr   r   r
   r   r)  _CheckForImmutableRevision_RemoteFetch
GetBooleanr   r   r  r   	_InitMRef_InitMirrorHead)rM   rq  r  Zis_newr  r  Zclone_bundler  archiver5  r  r  r  rY   r  r   r  Zaltr&   r  r  mpZ
dissociateZalternates_filer  r'   r'   r(   Sync_NetworkHalf  s    
"

(






zProject.Sync_NetworkHalfc             C   s   | j   d S )N)
_InitHooks)rM   r'   r'   r(   PostRepoUpgrade  s    zProject.PostRepoUpgradec             C   s@   | j jrd S x| jD ]}|j  qW x| jD ]}|j  q,W d S )N)r&  isGitcClientr7  r   r8  r   )rM   copyfileZlinkfiler'   r'   r(   r    s    zProject._CopyAndLinkFilesc             C   sZ   | j jts| j| jS y| jj| j dd S  tk
rT   td| j | j	f Y nX dS )zGet revisionId of a commit.

    Use this method instead of GetRevisionId to get the id of the commit rather
    than the id of the current git object (for example, a tag)

    z-1r   zrevision %s in %s not foundN)
r)  r  r   GetRevisionIdrU  rP   rQ   r   r   rY   )rM   r'   r'   r(   GetCommitRevisionId%  s    zProject.GetCommitRevisionIdc             C   s~   | j r| j S | j| jj}|j| j}|d k	r>||kr>|| S y| jjdd| S  tk
rx   t	d| j| jf Y nX d S )Nz--verifyz%s^0zrevision %s in %s not found)
r*  rS  rp   rY   ToLocalr)  rP   rb   r   r   )rM   rY  remrevr'   r'   r(   r  5  s    zProject.GetRevisionIdc          <      s  t jjjs*|jdjjf  dS j||d jj}j	| j
|fdd}fdd}jj }|jtr|ttd }y|| }W q tk
r   d}Y qX nd}|dks|jrj r|jt  dS |kr|js0j  dS n(jtt}	|	r0|jdt|	 y$jd	d
 |rRjd	d
 W n. tk
r }
 z|j|
 dS d}
~
X nX j  dS |krj  dS j|}|js(|jd|j y$jd	d
 |rjd	d
 W n. tk
r }
 z|j|
 dS d}
~
X nX j  dS jtt}yjjdt d}W n$ tk
rt   j|j|}Y nX |rjt|}|r|r|jd|jt|f  dS ||kr|j | |r|j | dS jttdd}d d}x6|D ].}|j!dd\}}|j"kr| |d7 }qW | rP|t|krPdS j#ddrp|jt$  dS |j%j&kr|j%rj&r|jd|j%j& n|j%r|jd|j% |t|k r|jdt||  j'j(j|_(t)j*j&s j&|_%|j%jds t|j% |_%|j+  |dkrj,rfdd} fdd}|j-| |rt|j-| |j-| n~|ry(j. |rjd	d
 j  W n. tk
r }
 z|j|
 dS d}
~
X nX n|j | |r |j | dS )zbPerform only the local IO portion of the sync process.
       Network access is not required.
    zLCannot checkout %s due to missing network sync; Run `repo sync -n %s` first.N)r  r  c                  s   j   j  d S )N)_FastForwardr  r'   )revidrM   r'   r(   _doffU  s    
z%Project.Sync_LocalHalf.<locals>._doffc                  s    j dd d S )NT)rq  )_SyncSubmodulesr'   )rM   r'   r(   _dosubmodulesY  s    z-Project.Sync_LocalHalf.<locals>._dosubmoduleszdiscarding %d commitsT)rq  z#leaving %s; does not track upstreamz--is-ancestorFzDbranch %s is published (but not merged) and is now %d commits behindz%H %ce)formatr    r   )rK  zmanifest switched %s...%szmanifest no longer tracks %sz+discarding %d commits removed from upstreamzrefs/c                  s    j   d S )N)r  r'   )rM   r'   r(   _docopyandlink  s    z.Project.Sync_LocalHalf.<locals>._docopyandlinkc                  s   j d  d d S )Nz%s^1)r1  onto)_Rebaser'   )	last_miner  rM   r'   r(   	_dorebase  s    z)Project.Sync_LocalHalf.<locals>._dorebase)/r:   r#   r   r#  r   rY   _InitWorkTreer=  r^  r  r  r   rB  r  r   rC  rm  detach_headrG  _PriorSyncFailedErrorr  _revlistr5   r   r  	_Checkoutr  r   rT  r  Z
merge_baser  later1rr   rq   rL  _DirtyErrorr  r)  rS  rp   r
   r   r  r+  later2
_ResetHard)rM   syncbufr  r  rY  r  r  headrX   Zlostr  Zupstream_gainZpubZ
not_mergedZlocal_changesZcnt_minerL   Z	commit_idZcommitter_emailr  r  r'   )r  r  rM   r(   Sync_LocalHalfE  s    










zProject.Sync_LocalHalfc             C   s   | j jt| j||| dS )a  Mark |src| for copying to |dest| (relative to |topdir|).

    No filesystem changes occur here.  Actual copying happens later on.

    Paths should have basic validation run on them before being queued.
    Further checking will be handled when the actual copy happens.
    N)r7  ra  r   r   )rM   r   r   r   r'   r'   r(   AddCopyFile  s    zProject.AddCopyFilec             C   s   | j jt| j||| dS )a#  Mark |dest| to create a symlink (relative to |topdir|) pointing to |src|.

    No filesystem changes occur here.  Actual linking happens later on.

    Paths should have basic validation run on them before being queued.
    Further checking will be handled when the actual link happens.
    N)r8  ra  r   r   )rM   r   r   r   r'   r'   r(   AddLinkFile  s    zProject.AddLinkFilec             C   s   | j jt||| d S )N)r9  ra  r   )rM   rY   r   r   r'   r'   r(   AddAnnotation  s    zProject.AddAnnotationc             C   sf   | j | jj}d|jg}|jd|d ||f  t| |ddj dkrJdS t| | j ||| jj	dS )	zBDownload a single patch set of a single change to FETCH_HEAD.
    fetchzrefs/changes/%2.2d/%d/%dd   T)r%  r   Nr  )
rS  rp   rY   ra  r   r  rG   r  rP   rb   )rM   rJ   Zpatch_idrp   r  r'   r'   r(   DownloadPatchSet  s    
zProject.DownloadPatchSetc          (      s  | j  r>|r$td| jf tjd ntd| jf tjd dS |sRtd| jf  | jrtj| j}| j	j
ddj d }|jd	st||d
d }tjj|d}xttj|D ]f}tjj||d}t|}	|	j j }
W dQ R X tjtjj|||
}||krtjtjj|| qW ytj| j W n tk
rD   Y nX ytj| j W nd tk
r } zF|jtjkrtd| j|f tjd td| jf tjd dS W Y dd}~X nX g  d}xtj| j
D ]\}}xx|D ]p}tjj|}ytj| W nL tk
rN } z.|jtjkr>td||f tjd d}W Y dd}~X nX qW fdd|D |dd<   fdd|D 7  qW xt D ]}tj|rytj| W nL tk
r } z.|jtjkrtd||f tjd d}W Y dd}~X nX nhtj|sytj| W nL tk
rl } z.|jtjkr\td||f tjd d}W Y dd}~X nX qW |rtd| jf tjd tdtjd dS | j
}xd|| jjkrytj| W n4 tk
r } z|jtjkrP W Y dd}~X nX tjj |}qW dS )a  Delete the source checkout and any other housekeeping tasks.

    This currently leaves behind the internal .repo/ cache state.  This helps
    when switching branches or manifest changes get reverted as we don't have
    to redownload all the git objects.  But we should do some GC at some point.

    Args:
      quiet: Whether to hide normal messages.
      force: Always delete tree even if dirty.

    Returns:
      True if the worktree was completely cleaned out.
    z>warning: %s: Removing dirty project: uncommitted changes lost.)r*   zCerror: %s: Cannot remove project: uncommitted changes are present.
Fz%s: Deleting obsolete checkout.rj  z--porcelainr   z	worktree 	   N	worktreesr#  zerror: %s: %szXerror: %s: Failed to delete obsolete checkout; remove manually, then run `repo sync -l`.zerror: %s: Failed to remove: %sTc                s(   g | ] }t jjt jj |d s|qS )z.git)r:   r#   r   r;   )r<   r>   )rootr'   r(   r?   }  s    z*Project.DeleteWorktree.<locals>.<listcomp>c                s,   g | ]$}t jj| krt jj|qS r'   )r:   r#   r;   )r<   r>   )dirs_to_remover  r'   r(   r?     s    z.error: %s: Failed to delete obsolete checkout.z0       Remove manually, then run `repo sync -l`.)!rL  r+   r   r,   r-   r3  r   rA   r#  rP   r   r   r  r   r:   r#   r;   rE   r   r  r   rmtreer"   r!   r  r  walkreversedr   rmdirr&  r   rC   )rM   rq  forceZneedleru   Z	commondirZconfigsrY   r#  fpr   Zfullpathr  Zfaileddirsfilesrx  r#   r>   r'   )r  r  r(   DeleteWorktree.  s    
	

zProject.DeleteWorktreer   c       	      C   s`  |s
| j }| jj }|t| kr$dS | jj}t| |krVt| d|dgdddj dkS | j|}| j	| j
j|_
||_|jjd rtj| rt| |_|dkr| j|}n| jj|}|jtry|| }W n tk
r   d}Y nX |o|o||kr,t| }| jj|| | jjt| |j  dS t| dd|j|gdddj dkr\|j  dS d	S )
z5Create a new branch off the manifest's revision.
    Tcheckoutz--)rz  r{  r   zrefs/Nz-bF)r)  r   rB  r   r=  r^  r   r  rT  rS  rp   rY   r  r  r
   r   r  rb   rm  
update_refsymbolic_refr   r  )	rM   rY   branch_merger   r  rY  rX   r  rw   r'   r'   r(   StartBranch  sJ    




zProject.StartBranchc             C   s   t | }| jj }||krdS | jj}y|| }W n tk
rF   dS X |jt rxy|| }W n tk
rv   d}Y nX ||krt| jjt	ddt |f  dS t
| d|dgdddj dkS )	zCheckout a local topic branch.

        Args:
          name: The name of the branch to checkout.

        Returns:
          True if the checkout succeeded; False if it didn't; None if the branch
          didn't exist.
    TN)r   z
ref: %s%s
r  z--)rz  r{  r   )r   r   rB  r=  r^  rm  r  r)   rF  r   r   r  )rM   rY   r  r  rY  r  r'   r'   r(   CheckoutBranch  s,    



zProject.CheckoutBranchc             C   s   t | }| jj}||krdS | jj }||krp|| }| j|}||krbt| jjtdd|  n| j	|dd t
| dd|gdddj d	kS )
zDestroy a local topic branch.

    Args:
      name: The name of the branch to abandon.

    Returns:
      True if the abandon succeeded; False if it didn't; None if the branch
      didn't exist.
    N)r   z%s
T)rq  rX   z-D)rz  r{  r   )r   r=  r^  r   rB  r  r)   rF  r   r  r   r  )rM   rY   r  rY  r  r  r'   r'   r(   AbandonBranch  s    


zProject.AbandonBranchc             C   s  | j }g }| j}xD|j D ]8}|jtr|ttd }|dksH||kr|j| qW | j|}|dk	r| jt	d |  r| j
dd r| jjt	 |j| |rD| jj }z<| jj| ddg}|j| t| |dddd}|j  W dtj|r| jj| n| jj| | j}X x&|D ]}t| |kr"| j  P q"W |r^||kr^|j| |j  g }	xH|D ]@}t| |krp| j|}|j}
|
s|}
|	jt| ||
 qpW |	S )	z;Prune any topic branches already merged into upstream.
    Nz...F)rK  rX   z-dT)r%  rz  r{  )rE  rU  rb  r  r   rC  ra  r  r  r   rL  r   
DetachHeadrP   rB  rc  r   r  r
   r   SetHeadr  sortrT  r  rW   )rM   cbkillleftrY   r  oldrD  rX   ZkeptrI   r'   r'   r(   
PruneHeads   sX    








zProject.PruneHeadsc                s    g  fdd  | j  S )Nc                s.   | sd S j |  x| D ]} |j qW d S )N)rc  r6  )r6  rv  )recresultr'   r(   r  ]  s
    

z-Project.GetRegisteredSubprojects.<locals>.rec)r6  )rM   r'   )r  r  r(   GetRegisteredSubprojectsZ  s    
z Project.GetRegisteredSubprojectsc                sf    fdd}t jdt jdfdddd  y| j }W n tk
rX   g S X || j|S )	Nc       	         sv   | |\}}|sg S  | ||}g }xJt ||D ]<\}}y|| }W n tk
r\   w2Y nX |j|||f q2W |S )N)ziprm  ra  )	r#  r  Z	sub_pathsZsub_urlsZsub_revsr  Zsub_pathZsub_urlZsub_rev)git_ls_treeparse_gitmodulesr'   r(   get_submodulesk  s    z.Project._GetSubmodules.<locals>.get_submodulesz^submodule\.(.+)\.path=(.*)$z^submodule\.(.+)\.url=(.*)$c       
         s  ddd| g}yt d |ddd| d}W n tk
r>   g g fS X |j dkrTg g fS g }tj \}}zybtj||jjd tj	| dd	|d
g}t d |ddd| d}|j dkrg g fS |jj
d}W n tk
r   g g fS X W d tj| X t }i  i x|D ]}|sqj|}	|	rL|j|	jd |	jd |	jd< qj|}	|	r|j|	jd |	jd|	jd< qqW t|} fdd|D fdd|D fS )Nzcat-fileZblobz%s:.gitmodulesT)rz  r{  r%  r#  r   zutf-8r   z--filez--listro   r   r   c                s   g | ]} j |d qS )r   )rX  )r<   rY   )ru  r'   r(   r?     s    zDProject._GetSubmodules.<locals>.parse_gitmodules.<locals>.<listcomp>c                s   g | ]} j |d qS )r   )rX  )r<   rY   )urlsr'   r(   r?     s    )r   r   r  tempfilemkstempr:   r   r   r   closerr   r   r"   rl  r   r  r   rk  )
r#  r  r  rv  Zgitmodules_linesr&   Ztemp_gitmodules_pathnamesrv   r   )re_pathre_url)ru  r  r(   r	    sR    








z0Project._GetSubmodules.<locals>.parse_gitmodulesc       	      S   s   d|dg}|j | ytd |ddd| d}W n tk
r@   g S X |j dkrRg S i }x:|jjdD ]*}|j srqd|j dd \}}|||< qdW |S )	Nzls-treez--T)rz  r{  r%  r#  r   ro   r      )rc  r   r   r  r   rr   r   )	r#  r  ru  r  rv  r  rv   Z
object_revZobject_pathr'   r'   r(   r    s     


z+Project._GetSubmodules.<locals>.git_ls_tree)r   r   r  r   r#  )rM   r
  r  r'   )r  r	  r  r  r(   _GetSubmodulesf  s    

.zProject._GetSubmodulesc             C   s   g }| j s|S x| j D ]\}}}| jj| |}| jj| ||\}}}}	| jjj|}
|
rj|j|
j  q|j	drt
jjd| jj |}t| jj|| jj| jj| jjd}t| j||||	||||| j| j| j| j| j| dd}|j| |j|j  qW |S )Nz..z%s/)r   r   r   r   T)r&  rY   rp   r#  r'  r   r   r)  r*  r+  r,  r-  r.  r/  r2  r4  )rA  r  r&  ZGetSubprojectNameZGetSubprojectPathsru  rX  rc  GetDerivedSubprojectsr  r   r   urljoinrp   r   r   rY   r   r   r   r  r+  r,  r-  r.  r/  ra  )rM   r  r  r#   r   rY   r   r   r#  r'  rH   rp   
subprojectr'   r'   r(   r    sH    

zProject.GetDerivedSubprojectstruer   c             C   sJ   | j jd}|dkrd}||k r2| j jdt| | j jd|f | dS )zEnable git repository extension |key| with |value|.

    Args:
      key: The extension to enabled.  Omit the "extensions." prefix.
      value: The value to use for the extension.
      version: The minimum git repository version needed.
    zcore.repositoryFormatVersionNr   zextensions.%s)r   GetIntr   r~  )rM   r  r   versionZfound_versionr'   r'   r(   EnableRepositoryExtension  s    	z!Project.EnableRepositoryExtensionc             C   s2   y| j jdd| j  dS  tk
r,   dS X d S )Nz--verifyz%s^0TF)rP   rb   r)  r   )rM   r'   r'   r(   r  	  s
    z"Project._CheckForImmutableRevisionc             C   sp   ddd|g}|j d| jj  |j d| j  |j | j t| ||ddd}|j dkrltd	| j|j	f d S )
Nr  z-vz-oz--remote=%sz--prefix=%s/T)r  rz  r{  r   zgit archive %s: %s)
ra  rp   r   r   r)  r   r  r   rY   r-   )rM   r  r  r  commandr'   r'   r(   r  	  s    zProject._FetchArchivec       %   
   C   s  d}d }| j js| jdkrd }	|	r&d}tj| jd k	r:d}|r| jjtr\| jttd  }|sh|d k	r| j	 r|rt
d| j  dS |r|	 r| jrtj| j }nd}|s| jj}d}| j|}|j rd}|r"|odtjj|krtjj|}tjj| jd}| j|}| jj}t|j }t }xt|jj D ]t\}}||kr||jtsf|j|r||||< |j| q<||krq<d| }|||< |j| |j| q<W g }g }x@t|D ]4}d|| |f }|j| ||kr|j| qW d	j|}d	j|}t || nd }d
g}|rZt!d3ddd |jd|  | j"d| jj |	rp|jd|	  n$tjj#tjj| jdr|jd |r|jd | j$s|jd |j| |r|jd |r|jd |
r|jd g }|s|jt%d|j&d  n|d k	r2|jd |j| | j jrJ| rJd }n| j}| j j r~|r~|	r~t!d4r~|j| nP|r| j}|d k	r|j' r|jd st(| }|jt%d!| |j&|  | j jr| r|jt%d|j&d  | s|	r|jd" n"|jd# |jt%d$|j&d%  |j)| d} xt*dD ]}!t+| |d|d| d&}"|"j, }#|#dkrd} P nr|! rd'|"j-krd(|"j-krt+| d)d*|gd|d+}$|$j, }#|#rLP qLn&|r|r|#d,krP n|#dk rP |st
d-| j|"j.f t/j-d. t0j1t2j3d/d0 qLW |rd|rV|d	krLt || n
t4j5| | j6j7d1d |r|r| j	 s| j8||||o|	d|d |d2S | S )5NFz
.repo/repoTz9Skipped fetching project %s (already have persistent ref)r  zpacked-refszrefs/_alt/%sz%s %s
r   r  r      r   zpartial clones)r   r0   z--filter=%sZpartialclonez
--depth=%sr  z--depth=2147483647z--quietz--update-head-okz--forcez--prunez--recurse-submodules=on-demandz+refs/heads/*:zrefs/heads/*tagr   r[      zrefs/z+%s:z	--no-tagsz--tagsz+refs/tags/*:zrefs/tags/*)r%  	ssh_proxymerge_outputrz  zerror:zgit remote prunerp   r  )r%  r     z%s:
%s)r*      -   z--all)rY   rq  r  r  r  r  r  r  )r   r  r   )r   r[   r  )9r&  IsMirrorr   r
   r   r)  r  r   rC  r  r+   rY   r1  rp   rS  PreConnectFetchr:   r#   r   rC   r;   r#  r=  r^  rl  valuesr   rV  WritesTor  rk  ra  r)   r   r  r   r   r~  r  r   r   rc  ranger   r  r-   r   r,   timesleeprandomrandintr   r"   rP   Z	pack_refsr  )%rM   rY   r  r  rq  r  r  r  r  r  r  r  r  Zis_sha1Ztag_namer  rp   ref_dirZpacked_refsrY  Zidstmpr4   r[  Ztmp_packed_linesZold_packed_linesrv   Z
tmp_packedZ
old_packedr  specrX   okZ_igitcmdretZprunecmdr'   r'   r(   r  	  s   































zProject._RemoteFetchc             C   sb  |r| j jjjds| jrdS | j| jj}|jd }t	j
 j|}t|dkrTdS tjj| jd}tjj| jd	}tjj|}tjj|}	| r| r|	 rdS |s| j|||||}|sdS d
g}
|r|
jd | js|
jd |
j| x|jD ]}|
jt|  qW |
jd t| |
ddj dk}tjj|rFtj| tjj|r^tj| |S )Nz
repo.depthFz/clone.bundlehttpr   persistent-httppersistent-httpszclone.bundlezclone.bundle.tmpr  z--quietz--update-head-okz+refs/tags/*:refs/tags/*T)r%  r   )r3  r   r4  r5  )r&  r  r   r   r0  rS  rp   rY   r   r   ForUserUrlInsteadOfr   r:   r#   r;   r#  r   _FetchBundlera  r   r  r~  r   r  r   r"   )rM   r  rq  r  rp   Z
bundle_urlZ
bundle_dstZ
bundle_tmpZ	exist_dstZ	exist_tmpr  rx  r0  r'   r'   r(   r  	  sJ    
 





zProject._ApplyCloneBundlec             C   sF  t jj|rtj| ddd|ddg}|r6|ddg7 }t jj|rtt j|j}|dkrj|d	d
|f g7 }n
tj| t||r\}}	|r|d|g7 }|	r|d|	g7 }n&dt jkrdt	j
kr|dt jd g7 }|jdrd|tdd   }n |jdrd|tdd   }||g7 }t r0tddj| |rHtd| j|f  |rRd ntj}
|rbd ntj}ytj||
|d}W n tk
r   dS X |j \}}|j}|dkr|stdt	jd dS |r| r|rtd| t	jd W d Q R X t jj|r>|dkr.| j||r.tj|| dS tj| dS ndS d S )NZcurlz--failz--outputz--netrcz
--locationz--silentz--show-errori   z--continue-atz%dz--cookiez--proxy
http_proxydarwinzpersistent-httpsr3  zpersistent-httpz%sr  z%s: Downloading bundle: %s)r   r-   F   z/Server does not provide clone.bundle; ignoring.)r*   r   T)r:   r#   r   r   r"   r   st_sizer	   environr,   platformr  rC  r   r   r;   r+   rY   r   r   STDOUTr   r!   r   r  r-   _IsValidBundler    )rM   ZsrcUrlZtmpPathZdstPathrq  r  r  size
cookiefileproxyr   r-   r  ru   r  Zcurlretr'   r'   r(   r8  )
  s`    






zProject._FetchBundlec             C   s\   yBt |d.}|jddkr dS |s2tdtjd dS W d Q R X W n tk
rV   dS X d S )Nrr     s   # v2 git bundle
Tz$Invalid clone.bundle file; ignoring.)r*   F)r   r  r+   r,   r-   r!   )rM   r#   rq  rx  r'   r'   r(   r@  g
  s    zProject._IsValidBundlec             C   sV   dg}|r|j d |j | |j d t| |j dkrR| jrRtd| j|f d S )Nr  z-qz--r   z%s checkout %s )ra  r   r  rU  r   rY   )rM   r  rq  r  r'   r'   r(   r  s
  s    


zProject._Checkoutc             C   sH   dg}|j | |j d t| |j dkrD| jrDtd| j|f d S )Nzcherry-pickz--r   z%s cherry-pick %s )ra  r   r  rU  r   rY   )rM   r  r  r'   r'   r(   _CherryPick}
  s    

zProject._CherryPickc             C   s2   d| j j|g}t| |dd}|j dkr.|jS d S )Nz	ls-remoteT)rz  r   )rp   rY   r   r  r   )rM   rt   r  rv  r'   r'   r(   	_LsRemote
  s
    zProject._LsRemotec             C   sR   dg}|j d |j | |j d t| |j dkrN| jrNtd| j|f d S )NZrevertz	--no-editz--r   z%s revert %s )ra  r   r  rU  r   rY   )rM   r  r  r'   r'   r(   _Revert
  s    


zProject._Revertc             C   sH   ddg}|r|j d |j | t| |j dkrDtd| j|f d S )Nresetz--hardz-qr   z%s reset --hard %s )ra  r   r  r   rY   )rM   r  rq  r  r'   r'   r(   r  
  s    

zProject._ResetHardc             C   s>   ddddg}|r|j d t| |j dkr:td| j d S )NZ	submoduleupdatez--initz--recursivez-qr   z*%s submodule update --init --recursive %s )ra  r   r  r   rY   )rM   rq  r  r'   r'   r(   r  
  s
    
zProject._SyncSubmodulesc             C   sN   dg}|d k	r|j d|g |j| t| |j dkrJtd| j|f d S )Nr+  z--ontor   z%s rebase %s )rc  ra  r   r  r   rY   )rM   r1  r  r  r'   r'   r(   r  
  s    
zProject._Rebasec             C   s@   dd|g}|r|j d t| |j dkr<td| j|f d S )Nr  z	--no-statz	--ff-onlyr   z%s merge %s )ra  r   r  r   rY   )rM   r  Zffonlyr  r'   r'   r(   r  
  s
    

zProject._FastForwardc              C   sV  t jj| j }t jj| j }y|rVt j| j | jj  | jrVt	drV| j
d | j| jkr\|rtt j| j |s||r| j| j| jddd y| j| j| jdd W n tk
rZ } z|rFtd	| j tjd
 yRtjtj| j | jrt jjtj| jrtjtj| j | j|d|dS  tk
rD   |Y nX |W Y d d }~X nX |r| jj}|jjdpzd}|s|rd|st jj|| jd }t jj|dd| jd }	t jj|dd| jd }
t jj|r|}n,t jj|	r|	}nt jj|
r|
}nd }|rdt jj|s@t jj|t jj| jd}tt jj| jdt jj|dd  | j |d | jjj}x2d D ]*}|j!|ddr| jj"||j| qW | jj"dd | jj"dd | jj#r| jj"dd n| jj"dd  W n\ tk
rP   |r(t jj| jr(tj| j |rJt jj| jrJtj| j  Y nX d S )!Nr   r  r   ZworktreeConfigFT)
share_refscopy_all)rJ  z Retrying clone after deleting %s)r*   )
mirror_gitr  rq  zrepo.referencer   z.gitz.repoprojectsr  r  zobjects/info/alternatesro   )rq  	user.name
user.email)include_defaultszfilter.lfs.smudgezgit-lfs smudge --skip -- %fzfilter.lfs.processzgit-lfs filter-process --skipz	core.barer  )r   r  r   )rN  rO  )$r:   r#   r   r#  r'  r   r>  initr3  r   r  _ReferenceGitDir_CheckDirReferencer   r+   r,   r-   r   r  rA   r   r  r  r&  r  r   r   r;   rY   r   isabsr)   r  Hasr   r$  )rM   rL  r  rq  Zinit_git_dirZinit_obj_dirr  r  r-  Zrepo_gitZworktrees_gitr   r  r'   r'   r(   r  
  s    





zProject._InitGitDirc             C   s   t jj| jr| j|d d S )N)rq  )r:   r#   r   r#  r  )rM   rq  r'   r'   r(   r  
  s    zProject._UpdateHooksc             C   sB  t j| jd}tjj|s&tj| xt D ]}tjj|}|dkrb| j	j
 rb| | jjk	rbq0tjj||}t j|r|q0tjj|rtj||dds0|s0td| j| q0y"t jtjj|tjj|| W q0 tk
r8 } zL|jtjkr&ytj|| W n" tk
r"   t| j Y nX n W Y d d }~X q0X q0W d S )Nr9   
commit-msgF)r  z*%s: Not replacing locally modified %s hook)rV  )r   rA   _gitdir_pathr:   r#   r   r   rF   r   rp   r   r&  r  r;   r   r   r   r2   r   r   rC   r!   r  EPERMlinkr   _get_symlink_error_message)rM   rq  r9   Z
stock_hookrY   dstr  r'   r'   r(   r    s6    


zProject._InitHooksc             C   sh   | j jrd| j| j j}| j j|_| j j|_| j j|_| j|_| jrP|jdd n|jdd |j	  d S )NF)mirrorT)
rp   r   rS  rY   r   r   r  r   
ResetFetchr  )rM   rp   r'   r'   r(   r  6  s    


zProject._InitRemotec             C   s   | j jr| jt| j j  d S )N)r&  rX   _InitAnyMRefr   )rM   r'   r'   r(   r  D  s    zProject._InitMRefc             C   s   | j t d S )N)r^  r   )rM   r'   r'   r(   r  H  s    zProject._InitMirrorHeadc             C   s   | j j|}| jrV|dks,| j j|| jkrd| j }| jd }| jj|||dd n>| j| jj}|j	| j
}||krd| j
 }| jjd||| d S )Nr   zmanifest set to %sz^0T)r  detachz-m)r=  symrefr*  rX  rP   r  rS  rp   rY   r  r)  r  )rM   rw   curr0   r[  rp   r'   r'   r(   r^  K  s    


zProject._InitAnyMRefc             C   sd  | j r
d S | jd d  }| jd d  }|r>|| j7 }|| j7 }|| }xt|D ]}tjj||}tjj||}	|| jkrtjj	|	stj
|	 n0|| jkrtjj	|	 rtjj|rtj||	 || jks|| jkrtjj	|	otjj	| rtjtjj|	tjj|| tj|}
tjj|
rRtj|	}||
krRtd||| tdj| jqRW d S )Nz%s is different in %s vs %sz--force-sync not enabled; cannot overwrite a local work tree. If you're comfortable with the possibility of losing the work tree's git metadata, use `repo sync --force-sync {0}` to proceed.)r3  shareable_filesshareable_dirsworking_tree_filesworking_tree_dirsrl  r:   r#   r;   r   r   r   r   r    r   r   rC   rA   r   r1   r   r  )rM   srcdirZdestdirrJ  symlink_filessymlink_dirs
to_symlinkrY   Zdst_pathro  r[  r   r'   r'   r(   rS  Z  s8    





zProject._CheckDirReferencec             C   s  | j dd }| jdd }|r4|| j7 }|| j7 }|| }g }|rNtj|}tj|}x`t|j|D ]L}	ytjt	j
j||	}
t	j
j||	}t	j
j|rwj|	|krt	j
j|
 rt	j|
 |	|krtjt	j
j|
t	j
j|| nF|otj| r2tj|
rtj|
| nt	j
j|
r2tj|
| |	|krrt	j
j|
 rrytj| W n tk
rp   Y nX W qj tk
r } z$|jtjkrt| j n W Y dd}~X qjX qjW dS )a  Update |dotgit| to reference |gitdir|, using symlinks where possible.

    Args:
      gitdir: The bare git repository. Must already be initialized.
      dotgit: The repository you would like to initialize.
      share_refs: If true, |dotgit| will store its refs under |gitdir|.
          Only one work tree can store refs under a given |gitdir|.
      copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|.
          This saves you the effort of initializing |dotgit| yourself.
    N)rb  rc  rd  re  r   rE   rA   rl  unionr:   r#   r;   r   r   r   r   rC   r   r   r   copytreer   r   r"   r!   r  rX  r   rZ  )rM   r#  dotgitrJ  rK  rg  rh  ri  Zto_copyrY   r   r[  r  r'   r'   r(   rR    sF    





zProject._ReferenceGitDirc             C   s   | j jd | j jddddd| j| j  tjj| jd}t|d0}|j }|jd	s\t	|j
d
dd j }W dQ R X tj| t|d }td	tjj|| j|d W dQ R X ttjj|dd}ttjj|||d W dQ R X dS )z%Init the project using git worktrees.r  r  z-ffz
--checkoutz--detachz--lockz.gitr4   zgitdir::r   Nr   )r*   r#  )rP   r   r  r:   r#   r;   r   r  r  r   rr   r   r   r"   r+   r   )rM   rl  r  settingZgit_worktree_pathr'   r'   r(   _InitGitWorktree  s    
zProject._InitGitWorktreec       	      C   s  t jj| jd}|d }t jj| }|rv| jrD| j  | j  d S |}tj	|dd t j
| | j| j|ddd n|}y| j| j|dd W nb tk
r } zF|r| rytj	| | jd|dS  tk
r   |Y nX |W Y d d }~X nX |r|tt jj|td	| j   tj|| d
ddg}|jd |jt t| |j dkrbtd| j |rt| jdd | j  d S )Nz.gitz.tmpT)ignore_errorsF)rJ  rK  )rJ  )r  r  z%s
z	read-treez--resetz-uz-vr   z Cannot initialize work tree for )rq  )r:   r#   r;   r   r   r3  ro  r  r   r  r   rR  r#  rS  r   r  r  r)   r   r  r    ra  r   r  rY   r  )	rM   r  r  Z
realdotgitZ	tmpdotgitZinit_dotgitrl  r  r  r'   r'   r(   r    sF    







zProject._InitWorkTreec             C   s   t j rdS dS )NzUnable to create symbolic link. Please re-run the command as Administrator, or see https://github.com/git-for-windows/git/wiki/Symbolic-Links for other options.z filesystem must support symlinks)r   	isWindows)rM   r'   r'   r(   rZ  	  s    z"Project._get_symlink_error_messagec             C   s   t jtjj| j|S )N)r   rA   r:   r#   r;   r#  )rM   r#   r'   r'   r(   rW    s    zProject._gitdir_pathc             O   s&   g }|j | |jd | jj||S )Nz--)rc  ra  r   rQ   )rM   r/   kwar'   r'   r(   r    s    

zProject._revlistc             C   s   | j jS )N)r=  r^  )rM   r'   r'   r(   rU    s    zProject._allrefsc             C   s   d}|r|g}|r |j ||g ddj|g}t| j}	|	jrL|rL|jd |dk	rb|jd|  |rp|jd y&t| |ddd	}
|
j d
kr|
jS W n8 t	k
r   t
jj| js| jj|dd  S  Y nX dS )z/Get logs between two revisions of this project.z..r_   r   z--colorNz--pretty=format:%sz	--onelineT)rz  r{  r   r   )rc  r;   r   r   r}  ra  r   r  r   r   r:   r#   r   r   rP   r_   )rM   Zrev1Zrev2onelinecolorpretty_formatcompZrevsr  rt  r_   r'   r'   r(   _getLogs  s,    




zProject._getLogsc             C   sP   i }| j | j}|j |j}| j|||||d|d< | j|||||d|d< |S )z;Get the list of logs from this revision to given revisionId)rt  ru  rv  r   Zremoved)r  rU  rx  )rM   Z	toProjectrt  ru  rv  r   ZselfIdZtoIdr'   r'   r(   getAddedAndRemovedLogs;  s    zProject.getAddedAndRemovedLogsc               @   sn   e Zd Zdd Zdd Zdd Zddd	Zd
d ZdddZdddZ	dddZ
dddZdd Zdd ZdS )zProject._GitGetByExecc             C   s   || _ || _|| _d S )N)_project_bare_gitdir)rM   rH   r%  r#  r'   r'   r(   rN   J  s    zProject._GitGetByExec.__init__c             C   sL   t | jddddgd| jddd}|j dkrH|j}|rH|d d jd
S g S )Nzls-filesz-zz--othersz--exclude-standardFT)r%  r#  rz  r{  r   r    r|  )r   rz  r|  r  r   rr   )rM   rv  rt  r'   r'   r(   rJ  O  s    zProject._GitGetByExec.LsOthersc       
      G   s  |g}|j d |j d |j| t| j|| jdddd}z|jjj }t|ds\|j	 }i }|rt
|d d jd}x|r
yt|}t|}W n tk
r   P Y nX G d	d
 d
t}	|dd  jd}|	|f| }|jdk r|j|_t||_|||j< q~W |S |j  X d S )Nz-zz--ignore-submodulesFT)r#  r%  rz  r{  r   r   r}  c               @   s   e Zd Zdd ZdS )z*Project._GitGetByExec.DiffZ.<locals>._Infoc             S   s   || _ d | _|| _|| _|| _|| _t|dkr>|| _d | _n>|d d | _|dd  | _x | jj	drz| jdd  | _q\W d S )Nr   0)
r#   ro  Zold_modeZnew_modeZold_idZnew_idrC  rz   rp  r  )rM   r#   ZomodeZnmodeoidnidstater'   r'   r(   rN   {  s    z3Project._GitGetByExec.DiffZ.<locals>._Info.__init__N)rS   rT   rU   rN   r'   r'   r'   r(   _Infoy  s   r  r  RCr|  )r  r  )ra  rc  r   rz  r|  r  r   r  r  r  iterrr   nextStopIterationobjectrz   r#   ro  r  )
rM   rY   r/   r  rv  rt  r4   r  r#   r  r'   r'   r(   rI  `  s@    




zProject._GitGetByExec.DiffZNc             C   s   | j r| j}nvtjj| jjd}tjj|rt|}|j	 }W dQ R X |j
dsVt|jddd j }tjjtjj| jj|}|dkr|S tjj||S )zcReturn the full path to the .git dir.

      As a convenience, append |subpath| if provided.
      z.gitNzgitdir:rm  r   )r{  r|  r:   r#   r;   rz  r   r   r   r  r  r   rr   r   r(  )rM   r   rl  r  rn  r#  r'   r'   r(   rF    s    
z#Project._GitGetByExec.GetDotgitPathc             C   s   | j td}y t|}|j }W dQ R X W n0 tk
r\ } zt|t|W Y dd}~X nX y|j }W n tk
r~   Y nX |j	dr|dd S |dd S )z#Return the ref that HEAD points to.)r   Nzref:    r   r|  r|  )
rF  r   r   r  r   r   r~  r  AttributeErrorr  )rM   r#   r&   rv   r  r'   r'   r(   rB    s    
 
zProject._GitGetByExec.GetHeadc             C   s<   g }|d k	r|j d|g |jt |j| | j|  d S )Nz-m)rc  ra  r   r  )rM   rw   r  cmdvr'   r'   r(   r    s    

zProject._GitGetByExec.SetHeadc             C   s>   dg}|d k	r|j d|g |jt |j| | j|  d S )Nz
--no-derefz-m)rc  ra  r   r  )rM   newr  r  r'   r'   r(   r    s    

z Project._GitGetByExec.DetachHeadFc             C   s\   g }|d k	r|j d|g |r(|jd |j| |j| |d k	rN|j| | j|  d S )Nz-mz
--no-deref)rc  ra  r  )rM   rY   r  r  r  r_  r  r'   r'   r(   r    s    



zProject._GitGetByExec.UpdateRefc             C   s.   |s| j |}| jd|| | jjj| d S )Nz-d)rb   r  rz  r=  deleted)rM   rY   r  r'   r'   r(   r    s    
zProject._GitGetByExec.DeleteRefc             O   sv   d|krdd|d  g}ndg}|j | t| j|| j| jddd}|j dkrltd| jjt||j	f |j
j S )	Nr  r_   z--pretty=format:%szrev-listT)r%  r#  rz  r{  r   z%s rev-list %s: %s)rc  r   rz  r{  r|  r  r   rY   r~  r-   r   r   )rM   r/   rr  r  rv  r'   r'   r(   rQ     s    
zProject._GitGetByExec.rev_listc                s    j dd  fdd}|S )a  Allow arbitrary git commands using pythonic syntax.

      This allows you to do things like:
        git_obj.rev_parse('HEAD')

      Since we don't have a 'rev_parse' method defined, the __getattr__ will
      run.  We'll replace the '_' with a '-' and try to run a git command.
      Any other positional arguments will be passed to the git command, and the
      following keyword arguments are supported:
        config: An optional dict of git config options to be passed with '-c'.

      Args:
        name: The name of the git command to call.  Any '_' characters will
            be replaced with '-'.

      Returns:
        A callable object that will try to call git with the named command.
      r  r_  c                 s   g }|j dd }x|D ]}td |f qW |d k	rhx0|j D ]$\}}|jd |jd||f  q@W |j  |j|  tj|jjddd}|j	 dkrt
djj |jf |j}|jd	r|jd	t|d
 kr|d d S |S )Nr   z*%s() got an unexpected keyword argument %rz-cz%s=%sT)r%  r#  rz  r{  r   z	%s %s: %sro   r   r|  )r   	TypeErrorrV  ra  rc  r   rz  r{  r|  r  r   rY   r-   r   endswithindexrC  )r/   r   r  r   kvrv  r4   )rY   rM   r'   r(   runner  s0    



 z1Project._GitGetByExec.__getattr__.<locals>.runner)r7   )rM   rY   r  r'   )rY   rM   r(   __getattr__  s    z!Project._GitGetByExec.__getattr__)N)N)N)NNF)N)rS   rT   rU   rN   rJ  rI  rF  rB  r  r  r  r  rQ   r  r'   r'   r'   r(   r<  H  s   6


  

r<  )TNFFTNNNFFNFN)T)T)NF)F)N)N)N)N)FFNFFTTFFFFN)N)FF)FF)r   N)r  r   )N)NFFFFNTFNFFN)FFF)F)T)T)N)F)NFF)F)F)FF)FTN)FTN)UrS   rT   rU   rb  rc  rd  re  rN   rV   r@  rA  rE  rG  rL  rM  rP  rO  rq   rN  rS  rT  r\  r`  rf  rg  ry  r  r  r  r  r  rn   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r8  r@  r  rE  rF  rG  r  r  r  r  r  r  r  r  r  r  r^  rS  rR  ro  r  rZ  rW  r  rU  rx  ry  r  r<  r'   r'   r'   r(   r  P  s   
            
T
	

$
[
%


L
           
h

 C


u
/,":`+


           
 W
.>

	




W

(.:
.
 
r  c               @   s   e Zd Zdd ZdS )r  c             C   s   dS )Nz+prior sync failed; rebase still in progressr'   )rM   r'   r'   r(   __str__!  s    z_PriorSyncFailedError.__str__N)rS   rT   rU   r  r'   r'   r'   r(   r    s   r  c               @   s   e Zd Zdd ZdS )r  c             C   s   dS )Nzcontains uncommitted changesr'   )rM   r'   r'   r(   r  '  s    z_DirtyError.__str__N)rS   rT   rU   r  r'   r'   r'   r(   r  %  s   r  c               @   s   e Zd Zdd Zdd ZdS )_InfoMessagec             C   s   || _ || _d S )N)rH   text)rM   rH   r  r'   r'   r(   rN   -  s    z_InfoMessage.__init__c             C   s$   |j jd| jj| j |j j  d S )Nz%s/: %s)rt  r  rH   r   r  ri  )rM   r  r'   r'   r(   Print1  s    z_InfoMessage.PrintN)rS   rT   rU   rN   r  r'   r'   r'   r(   r  +  s   r  c               @   s   e Zd Zdd Zdd ZdS )_Failurec             C   s   || _ || _d S )N)rH   why)rM   rH   r  r'   r'   r(   rN   8  s    z_Failure.__init__c             C   s(   |j jd| jjt| j |j j  d S )Nzerror: %s/: %s)rt  r   rH   r   r~  r  ri  )rM   r  r'   r'   r(   r  <  s    z_Failure.PrintN)rS   rT   rU   rN   r  r'   r'   r'   r(   r  6  s   r  c               @   s   e Zd Zdd Zdd ZdS )_Laterc             C   s   || _ || _d S )N)rH   action)rM   rH   r  r'   r'   r(   rN   E  s    z_Later.__init__c             C   sT   |j }|jd| jj |j  y| j  |j  dS  tk
rN   |j  dS X d S )Nzproject %s/TF)rt  rH   r   ri  r  r   )rM   r  rt  r'   r'   r(   r  I  s    z
_Later.RunN)rS   rT   rU   rN   r  r'   r'   r'   r(   r  C  s   r  c               @   s   e Zd Zdd ZdS )_SyncColoringc             C   s>   t j| |d | jddd| _| jd| _| jddd| _d S )	NZreposyncr{   r|   )r}   r  r   r   )r   )r   rN   r   rH   r  r   )rM   r   r'   r'   r(   rN   X  s    z_SyncColoring.__init__N)rS   rT   rU   rN   r'   r'   r'   r(   r  V  s   r  c               @   sh   e Zd ZdddZdd ZdddZd	d
 Zdd Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )
SyncBufferFc             C   sF   g | _ g | _g | _g | _t|| _| jjtj || _	d| _
d| _d S )NT)	_messages	_failures_later_queue1_later_queue2r  rt  rh  r,   r-   r  cleanrecent_clean)rM   r   r  r'   r'   r(   rN   a  s    
zSyncBuffer.__init__c             G   s   | j jt|||  d S )N)r  ra  r  )rM   rH   r.   r/   r'   r'   r(   r  n  s    zSyncBuffer.infoNc             C   s   | j jt|| | j  d S )N)r  ra  r  _MarkUnclean)rM   rH   errr'   r'   r(   r   q  s    zSyncBuffer.failc             C   s   | j jt|| d S )N)r  ra  r  )rM   rH   whatr'   r'   r(   r  u  s    zSyncBuffer.later1c             C   s   | j jt|| d S )N)r  ra  r  )rM   rH   r  r'   r'   r(   r  x  s    zSyncBuffer.later2c             C   s   | j   | j  | j   | jS )N)_PrintMessages	_RunLaterr  )rM   r'   r'   r(   Finish{  s    zSyncBuffer.Finishc             C   s   | j }d| _ |S )NT)r  )rM   r  r'   r'   r(   Recently  s    zSyncBuffer.Recentlyc             C   s   d| _ d| _d S )NF)r  r  )rM   r'   r'   r(   r    s    zSyncBuffer._MarkUncleanc             C   s    xdD ]}| j |sd S qW d S )Nr  r  )r  r  )	_RunQueue)rM   qr'   r'   r(   r    s    

zSyncBuffer._RunLaterc             C   s:   x(t | |D ]}|j| s| j  dS qW t| |g  dS )NFT)getattrr  r  setattr)rM   queuer   r'   r'   r(   r    s    
zSyncBuffer._RunQueuec             C   st   | j s| jr0tjdr$| jjtj | jjd x| j D ]}|j|  q8W x| jD ]}|j|  qRW g | _ g | _d S )Nr   )	r  r  r:   r   rt  r   progressCSI_ERASE_LINEr  )rM   r   r'   r'   r(   r    s    
zSyncBuffer._PrintMessages)F)N)rS   rT   rU   rN   r  r   r  r  r  r  r  r  r  r  r'   r'   r'   r(   r  _  s   

r  c               @   sB   e Zd ZdZdd Zdd ZdddZed	d
 Zedd Z	dS )r  z(A special project housed under .repo.
  c             C   s,   t j| |||||tdd| dd d d d S )Noriginz.repo/%szrefs/heads/master)
r&  rY   r#  r'  r   rp   r   r)  r*  r,  )r  rN   r   )rM   r&  rY   r#  r   r'   r'   r(   rN     s    zMetaProject.__init__c             C   s0   | j r,| j}|r,| j|j}|r,|| _d | _d S )N)rA  rE  rT  r  r)  r*  )rM   r  rI   r'   r'   r(   PreSync  s    zMetaProject.PreSyncFc             C   sB   t | jdd}| j||d |j  t| dddgdddj dkS )	z4 Prepare MetaProject for manifest branch switch
    T)r  )r  z
update-refz-dzrefs/heads/default)rz  r{  r   )r  r   r  r  r   r  )rM   r  r  r'   r'   r(   MetaBranchSwitch  s    zMetaProject.MetaBranchSwitchc             C   s6   yt jj| jd}t jj|S  tk
r0   dS X d S )Nr  r   )r:   r#   r;   r#  getmtimer!   )rM   Zfhr'   r'   r(   	LastFetch  s
    zMetaProject.LastFetchc             C   s   | j  s| j rdS | jj}| j|}| jj }|jtr`y|| }W n t	k
r^   d}Y nX ||krldS | j
tt|rdS dS )z=Has the remote received new commits not yet checked out?
    FNT)rp   r)  r=  r^  r  r   rB  r  r   rm  r  r5   r   )rM   rY  r  r  r'   r'   r(   rg    s    



zMetaProject.HasChangesN)F)
rS   rT   rU   r   rN   r  r  rV   r  rg  r'   r'   r'   r(   r    s   	
r  )F)V
__future__r   r  r   r   r   r:   r+  r   r   r   r   r,   r  r  r)  r  ru  r   git_commandr   r   
git_configr   r   r   r	   r
   errorr   r   r   r   r   r   r   r   r  
repo_tracer   r   git_refsr   r   r   r   r   r   	pyversionr   urllib.parser   impr   
new_moduler   	raw_inputr   r)   r1   r2   r5   r8   r@   rF   r  rG   rW   ry   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r  r'   r'   r'   r(   <module>   s    

g
)/I                      b	G