
zzRc           @   s   d  Z  d d l Z d d l Z d d l Z d d l m Z d d l j Z d d l	 m
 Z
 d d l m Z d d l m Z d d l m Z d d l m Z d	 e f d
     YZ d e f d     YZ d e f d     YZ d S(   s   A Git repositoryiN(   t   defaultdict(   t   GbpError(   t   GitModifier(   t	   GitCommit(   t   GitError(   t   GitArgst   GitRepositoryErrorc           B   s   e  Z d  Z RS(   s$   Exception thrown by L{GitRepository}(   t   __name__t
   __module__t   __doc__(    (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR       s   t	   GitRemotec           B   sM   e  Z d  Z d   Z d   Z e d    Z e d    Z e d    Z RS(   s&   Class representing a remote repositoryc         C   sP   | |  _  | |  _ t | t  r0 | g |  _ n g  | D] } | ^ q7 |  _ d  S(   N(   t   _namet
   _fetch_urlt
   isinstancet
   basestringt
   _push_urls(   t   selft   namet	   fetch_urlt	   push_urlst   url(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   __init__'   s
    		c         C   s   |  j  S(   N(   R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   __str__/   s    c         C   s   |  j  S(   s   Name of the remote(   R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   2   s    c         C   s   |  j  S(   s	   Fetch URL(   R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   7   s    c         C   s   |  j  S(   s   List of push URLs(   R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   <   s    (	   R   R   R	   R   R   t   propertyR   R   R   (    (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR
   %   s   		t   GitRepositoryc           B   s  e  Z d  Z d   Z d   Z e d    Z g  d\ d\ d  Z d\ d\ d\ e	 d  Z
 e d    Z g  d\ d  Z d   Z e d	    Z e d
    Z e d    Z e d    Z e d    Z e d    Z d   Z d\ d  Z e	 d  Z d   Z e	 d  Z d   Z d   Z d   Z e	 e	 d  Z d   Z e	 d  Z  d   Z! d   Z" d\ d\ d  Z# e	 d  Z$ d   Z% d   Z& d\ d\ e	 d\ d   Z' d!   Z( d"   Z) d#   Z* d\ e	 e	 d\ e	 e	 d$  Z+ d\ d%  Z, d\ d&  Z- d'   Z. e	 d(  Z/ d)   Z0 e	 d*  Z1 e	 e	 e	 d+  Z2 d,   Z3 d- d.  Z4 e d- d/   Z5 d0   Z6 d1   Z7 d\ d2  Z8 d3   Z9 d4   Z: e	 d\ d5  Z; d6   Z< d7   Z= d8   Z> d9   Z? d:   Z@ eA e	 d;  ZB d<   ZC d\ e	 d- d\ e	 d=  ZD d\ e	 e	 d>  ZE d\ d\ d\ eA e	 e	 d?  ZF d@   ZG e	 d\ d\ dA  ZH e	 dB  ZI dC g dD  ZJ eA dE  ZK g  d\ dF  ZL d\ e	 dG  ZM d\ e	 dH  ZN d\ dI  ZO d\ i  i  e	 dJ  ZP i  i  dK  ZQ d\ d\ d\ d- e	 d\ dL  ZR dM   ZS d\ dN  ZT dO   ZU dP   ZV eA d\ eA dQ  ZW eA d\ d\ dR  ZX d\ d\ e	 e	 e	 eA dS  ZY dT   ZZ e	 dU  Z[ dV   Z\ dW   Z] eA eA e	 dX  Z^ d\ eA dY  Z_ e d\ e	 dZ   Z` e d- e	 e	 e	 eA d[   Za RS(]   s  
    Represents a git repository at I{path}. It's currently assumed that the git
    repository is stored in a directory named I{.git/} below I{path}.

    @ivar _path: The path to the working tree
    @type _path: C{str}
    @ivar _bare: Whether this is a bare repository
    @type _bare: C{bool}
    @raises GitRepositoryError: on git errors GitRepositoryError is raised by
        all methods.
    c         C   s}   |  j  d d g d t \ } } } | r@ t d |  j   n  | j   d k rX t n t |  _ |  j rp d n d |  _ d S(	   s'   Check whether this is a bare repositorys	   rev-parses   --is-bare-repositoryt   capture_stderrs&   Failed to get repository state at '%s't   truet    s   .gitN(   t
   _git_inoutt   TrueR   t   patht   stript   Falset   _baret   _git_dir(   R   t   outt   dummyt   ret(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _check_bareO   s    !c         C   s   t  j j |  |  _ t |  _ yV |  j d d g d t \ } } } | sW | j   rs t	 d |  j | f   n  Wn- t	 k
 r   n t	 d |  j   n X|  j
   d  S(   Ns	   rev-parses   --show-cdupR   s   No Git repository at '%s': '%s's   No Git repository at '%s'(   t   osR   t   abspatht   _pathR    R!   R   R   R   R   R&   (   R   R   R#   R$   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   Y   s    	 c         C   s5   d } |  d k	 r1 t j j   } | j |   n  | S(   s(   Prepare environment for subprocess callsN(   t   NoneR'   t   environt   copyt   update(   t	   extra_envt   env(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   __build_envg   s
    c   	      C   s   g  } | s |  j  } n  |  j |  } d | g | } t j |  t j | d t j d | d | } x) | j   d k r | | j	 j
   7} qk W| | j	 j
   7} | | j f S(   sL  
        Run a git command and return the output

        @param command: git command to run
        @type command: C{str}
        @param args: list of arguments
        @type args: C{list}
        @param extra_env: extra environment variables to pass
        @type extra_env: C{dict}
        @param cwd: directory to swith to when running the command, defaults to I{self.path}
        @type cwd: C{str}
        @return: stdout, return code
        @rtype: C{tuple} of C{list} of C{str} and C{int}

        @deprecated: use L{gbp.git.repository.GitRepository._git_inout} instead.
        t   gitt   stdoutR/   t   cwdN(   R   t   _GitRepository__build_envt   logt   debugt
   subprocesst   Popent   PIPEt   pollR*   R2   t	   readlinest
   returncode(	   R   t   commandt   argsR.   R3   t   outputR/   t   cmdt   popen(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _git_getoutputp   s    $c         C   s.   | s |  j  } n  |  j | | | | | |  S(   s6  
        Run a git command with input and return output

        @param command: git command to run
        @type command: C{str}
        @param input: input to pipe to command
        @type input: C{str}
        @param args: list of arguments
        @type args: C{list}
        @param extra_env: extra environment variables to pass
        @type extra_env: C{dict}
        @param capture_stderr: whether to capture stderr
        @type capture_stderr: C{bool}
        @return: stdout, stderr, return code
        @rtype: C{tuple} of C{str}, C{str}, C{int}
        (   R   t   _GitRepository__git_inout(   R   R=   R>   t   inputR.   R3   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR      s    c         C   s   d | g | } |  j  |  } | r. t j n d }	 | rC t j n d }
 t j |  t j | d |
 d t j d |	 d | d t d | } | j |  \ } } | | | j	 f S(	   sC   
        As _git_inout but can be used without an instance
        R1   t   stdinR2   t   stderrR/   t	   close_fdsR3   N(
   R4   R7   R9   R*   R5   R6   R8   R   t   communicateR<   (   t   clsR=   R>   RD   R.   R3   R   R@   R/   t
   stderr_argt	   stdin_argRA   R2   RF   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   __git_inout   s    		c         C   s   y7 |  j  d | d | d d d | d t  \ } } } Wn) t k
 rb } t d | | f   n X| r t d | | f   n  d S(   s\  
        Execute git command with arguments args and environment env
        at path.

        @param command: git command
        @type command: C{str}
        @param args: command line arguments
        @type args: C{list}
        @param extra_env: extra environment variables to set when running command
        @type extra_env: C{dict}
        R=   R>   RD   R.   R   s   Error running git %s: %sN(   R   R*   R   t	   ExceptionR   (   R   R=   R>   R.   R2   RF   R%   t   excobj(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _git_command   s    c         C   s  t  | d  } |  j d | j d i d d 6d t \ } } } | rc t d | | d  f   n  t j d	  } t j d
  } t j d  }	 d }
 x| j   D]
} |
 d k r| j	 d  r| j
 d  } x | D] } | j   } |	 j |  } | rQ| j t j |	 d |   | j d  j d  } t j |	 d | |  } n  | j |  } | r | j d  | k r t Sq Wn  | j |  } | r | j d  }
 q q Wt S(   s(  
        Check if the git command has certain feature enabled.

        @param command: git command
        @type command: C{str}
        @param feature: feature / command option to check
        @type feature: C{str}
        @return: True if feature is supported
        @rtype: C{bool}
        s   -mt   helpR.   t   Ct   LC_ALLR   s   Invalid git command '%s': %sis   ^(?P<section>[A-Z].*)s   --?(?P<name>[a-zA-Z\-]+).*s   --\[(?P<prefix>[a-zA-Z\-]+)\]-?t   OPTIONSs          -t   ,s   --t   prefixt   -s   --%s-R   t   sectionN(   R   R   R>   R   R   t   ret   compileR*   t
   splitlinest
   startswitht   splitR   t   matcht   appendt   subt   groupR    (   R   R=   t   featureR>   RP   RF   R%   t
   section_ret	   option_ret	   optopt_ret   man_sectiont   linet   optst   optR]   RU   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _cmd_has_feature   s:    		c         C   s   |  j  S(   s#   The absolute path to the repository(   R)   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR      s    c         C   s   t  j j |  j |  j  S(   s#   The absolute path to git's metadata(   R'   R   t   joinR"   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   git_dir  s    c         C   s   |  j  S(   s    Wheter this is a bare repository(   R!   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   bare  s    c         C   s
   |  j    S(   s"   List of all tags in the repository(   t   get_tags(   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   tags  s    c         C   s'   y |  j    SWn t k
 r" d SXd S(   s    The currently checked out branchN(   t
   get_branchR   R*   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   branch  s    c         C   s   |  j  d  S(   s#   return the SHA1 of the current HEADt   HEAD(   t	   rev_parse(   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   head  s    c         C   s)   t  d | |  } |  j d | j  d S(   s   
        Rename branch

        @param branch: name of the branch to be renamed
        @param newbranch: new name of the branch
        s   -mRp   N(   R   RO   R>   (   R   Rp   t	   newbranchR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   rename_branch   s    c         C   s3   t  |  } | j | |  |  j d | j  d S(   s   
        Create a new branch

        @param branch: the branch's name
        @param rev: where to start the branch from

        If rev is None the branch starts form the current HEAD.
        Rp   N(   R   t   add_trueRO   R>   (   R   Rp   t   revR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   create_branch*  s    	c         C   s^   t  d  } | j | d  | j |  |  j | k rN |  j d | j  n t d   d S(   s   
        Delete branch I{branch}

        @param branch: name of the branch to delete
        @type branch: C{str}
        @param remote: delete a remote branch
        @param remote: C{bool}
        s   -Ds   -rRp   s!   Can't delete the branch you're onN(   R   Rv   t   addRp   RO   R>   R   (   R   Rp   t   remoteR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   delete_branch7  s    	c         C   s   |  j  d d g d t \ } } } | r9 t d   n  | j d  d } y! |  j d | g  | d } Wn t k
 r d	 } n X| S(
   s   
        On what branch is the current working copy

        @return: current branch or C{None} in an empty repo
        @rtype: C{str}
        @raises GitRepositoryError: if HEAD is not a symbolic ref
          (e.g. when in detached HEAD state)
        s   symbolic-refRq   R   s   Currently not on a branchs   
i    s   show-refi   N(   R   R   R   R\   RO   R*   (   R   R#   R$   R%   t   refRp   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRo   I  s    	
c         C   sM   | r d | } n
 d | } y |  j  d | g  Wn t k
 rH t SXt S(   s*  
        Check if the repository has branch named I{branch}.

        @param branch: branch to look for
        @param remote: only look for remote branches
        @type remote: C{bool}
        @return: C{True} if the repository has this branch, C{False} otherwise
        @rtype: C{bool}
        s   refs/remotes/%ss   refs/heads/%ss   show-ref(   RO   R   R    R   (   R   Rp   Rz   R|   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   has_branchc  s    

c         C   sP   |  j  | k r d S|  j r9 |  j d d d | g  n |  j d | g  d S(   s   
        Switch to branch I{branch}

        @param branch: name of the branch to switch to
        @type branch: C{str}
        Ns   symbolic-refRq   s   refs/heads/%st   checkout(   Rp   Rl   RO   (   R   Rp   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   set_branchw  s    		c         C   s\   y* |  j  d |  } |  j  d |  } Wn t k
 r> d SX| | j d d d  7} | S(   s}   
        Get the branch we'd merge from

        @return: repo and branch we would merge from
        @rtype: C{str}
        s   branch.%s.remotes   branch.%s.merges
   refs/headsR   i   N(   t
   get_configt   KeyErrorR*   t   replace(   R   Rp   Rz   t   merge(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_merge_branch  s    c         C   st   t    } | j |  | j |  |  j d | j d t \ } } } | sZ |  j |  St d | j     d S(   s<  
        Get the common ancestor between two commits

        @param commit1: commit SHA1 or name of a branch or tag
        @type commit1: C{str}
        @param commit2: commit SHA1 or name of a branch or tag
        @type commit2: C{str}
        @return: SHA1 of the common ancestor
        @rtype: C{str}
        s
   merge-baseR   s!   Failed to get common ancestor: %sN(   R   Ry   R   R>   R   t
   strip_sha1R   R   (   R   t   commit1t   commit2R>   t   sha1RF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_merge_base  s    	$c         C   su   t    } | j | d d  |  j d d  rD | j | d d  n t j d  | j |  |  j d | j  d S(	   s  
        Merge changes from the named commit into the current branch

        @param commit: the commit to merge from (usually a branch name or tag)
        @type commit: C{str}
        @param verbose: whether to print a summary after the merge
        @type verbose: C{bool}
        @param edit: wheter to invoke an editor to edit the merge message
        @type edit: C{bool}
        s	   --summarys   --no-summaryR   t   edits   --edits	   --no-editsE   Your git suite doesn't support --edit/--no-edit option for git-merge N(   R   t   add_condRi   R5   R6   Ry   RO   R>   (   R   t   committ   verboseR   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s    	c         C   s   t  } t  } |  j d d d | | f d g  d } | sE t t f Sx> | D]6 } | j d  rj t } qL | j d  rL t } qL qL W| r | r t  t  f S| r t  t f S| r t t  f Sd S(	   s   
        Check if an update I{from from_branch} to I{to_branch} would be a fast
        forward or if the branch is up to date already.

        @return: can_fast_forward, up_to_date
        @rtype: C{tuple}
        s   rev-lists   --left-rights   %s...%ss   --i    t   <t   >N(   R    RB   R   R[   (   R   t   from_brancht	   to_brancht	   has_localt
   has_remoteR#   Rf   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   is_fast_forward  s$    
	

c         C   sX   d g } | | r d g n d g 7} |  j  d |  d } g  | D] } | j   ^ qB S(   s   
        Get a list of branches

        @param remote: whether to list local or remote branches
        @type remote: C{bool}
        @return: local or remote branches
        @rtype: C{list}
        s   --format=%(refname:short)s   refs/remotes/s   refs/heads/s   for-each-refi    (   RB   R   (   R   Rz   R>   R#   R|   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _get_branches  s    		c         C   s   |  j  d t  S(   sg   
        Get a list of local branches

        @return: local branches
        @rtype: C{list}
        Rz   (   R   R    (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_local_branches  s    c         C   s   |  j  d t  S(   si   
        Get a list of remote branches

        @return: remote branches
        @rtype: C{list}
        Rz   (   R   R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_remote_branches  s    c         C   sO   | | g } | r" | | g 7} n  | r; d | g | } n  |  j  d |  d S(   sq  
        Update ref I{ref} to commit I{new} if I{ref} currently points to
        I{old}

        @param ref: the ref to update
        @type ref: C{str}
        @param new: the new value for ref
        @type new: C{str}
        @param old: the old value of ref
        @type old: C{str}
        @param msg: the reason for the update
        @type msg: C{str}
        s   -ms
   update-refN(   RO   (   R   R|   t   newt   oldt   msgR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   update_ref  s    c         C   s   t    } | j | d  | j d  | j |  |  j d | j  \ } } x6 | D]. } | j d d  } | j   | k rU t SqU Wt S(   sS  
        Check if branch I{branch} contains commit I{commit}

        @param branch: the branch the commit should be on
        @type branch: C{str}
        @param commit: the C{str} commit to check
        @type commit: C{str}
        @param remote: whether to check remote instead of local branches
        @type remote: C{bool}
        s   -rs
   --containsRp   t   *R   (	   R   Rv   Ry   RB   R>   R   R   R   R    (   R   Rp   R   Rz   R>   R#   R%   Rf   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   branch_contains  s    	c   	      C   s   xN | t  f | t f g D]4 \ } } |  j | d | s t d |   q q W|  j d d  rv d | | g } n d | | g } |  j d | d t \ } } } | r t d | | | j   f   n  d	 S(
   s   
        Set upstream branches for local branch

        @param local_branch: name of the local branch
        @type local_branch: C{str}
        @param upstream: remote/branch, for example origin/master
        @type upstream: C{str}
        Rz   s   Branch %s doesn't exist!Rp   s   set-upstream-tos   --set-upstream-to=%ss   --set-upstreamR   s/   Failed to set upstream branch '%s' for '%s': %sN(   R    R   R}   R   Ri   R   R   (	   R   t   local_brancht   upstreamRp   Rz   R>   R$   t   errR%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   set_upstream_branch+  s    %	c         C   sl   t  d  } |  j | d t r5 | j d |  n t d |   |  j d | j  d } | d j   S(   s   
        Get upstream branch for the local branch

        @param local_branch: name fo the local branch
        @type local_branch: C{str}
        @return: upstream (remote/branch) or  '' if no upstream found
        @rtype: C{str}

        s   --format=%(upstream:short)Rz   s   refs/heads/%ss   Branch %s doesn't exist!s   for-each-refi    (   R   R}   R    Ry   R   RB   R>   R   (   R   R   R>   R#   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_upstream_branchG  s    
c         C   s   g  } | | r d | g n g  7} | rT | d g 7} | | rJ d | g n g  7} n  | | g 7} | | rs | g n g  7} |  j  d |  d S(   s  
        Create a new tag.

        @param name: the tag's name
        @type name: C{str}
        @param msg: The tag message.
        @type msg: C{str}
        @param commit: the commit or object to create the tag at, default
            is I{HEAD}
        @type commit: C{str}
        @param sign: Whether to sing the tag
        @type sign: C{bool}
        @param keyid: the GPG keyid used to sign the tag
        @type keyid: C{str}
        s   -ms   -ss   -ut   tagN(   RO   (   R   R   R   R   t   signt   keyidR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   create_tag]  s    c         C   s,   |  j  |  r( |  j d d | g  n  d S(   sl   
        Delete a tag named I{tag}

        @param tag: the tag to delete
        @type tag: C{str}
        R   s   -dN(   t   has_tagRO   (   R   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   delete_tagv  s    c         C   s'   |  j  d | | g  |  j |  d  S(   NR   (   RO   R   (   R   R   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   move_tag  s    c         C   s2   |  j  d d | g  \ } } t t g t |  S(   s   
        Check if the repository has a tag named I{tag}.

        @param tag: tag to look for
        @type tag: C{str}
        @return: C{True} if the repository has that tag, C{False} otherwise
        @rtype: C{bool}
        R   s   -l(   RB   R    R   t   len(   R   R   R#   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s    	c         C   s  t    } | j | d | g  | j | d  | rQ | d k rQ | j d  n  | d k	 rq | j d |  n  | j | d  | j | d  | j | d  | j |  |  j d	 | j d
 t \ }	 }
 } | r t d | |
 j   f   n  |	 j   S(   s~  
        Describe commit, relative to the latest tag reachable from it.

        @param commitish: the commit-ish to describe
        @type commitish: C{str}
        @param pattern: only look for tags matching I{pattern}
        @type pattern: C{str}
        @param longfmt: describe the commit in the long format
        @type longfmt: C{bool}
        @param always: return commit sha1 as fallback if no tag is found
        @type always: C{bool}
        @param abbrev: abbreviate sha1 to given length instead of the default
        @type abbrev: None or C{long}
        @param tags: enable matching a lightweight (non-annotated) tag
        @type tags: C{bool}
        @param exact_match: only output exact matches (a tag directly
        references the supplied commit)
        @type exact_match: C{bool}
        @return: tag name plus/or the abbreviated sha1
        @rtype: C{str}
        s   --matchs   --longi    s   --abbrev=40s   --abbrev=%ss   --alwayss   --tagss   --exact-matcht   describeR   s    Can't describe %s. Git error: %sN(	   R   Rv   Ry   R*   R   R>   R   R   R   (   R   t	   commitisht   patternt   longfmtt   alwayst   abbrevRn   t   exact_matchR>   R   R   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s"    	c         C   s   |  j  | | d d S(   s  
        Find the closest tag to a given commit

        @param commit: the commit to describe
        @type commit: C{str}
        @param pattern: only look for tags matching I{pattern}
        @type pattern: C{str}
        @return: the found tag
        @rtype: C{str}
        R   i    (   R   (   R   R   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   find_tag  s    c         C   sE   | r d | g n g  } g  |  j  d |  d D] } | j   ^ q/ S(   s   
        List tags

        @param pattern: only list tags matching I{pattern}
        @type pattern: C{str}
        @return: tags
        @rtype: C{list} of C{str}
        s   -lR   i    (   RB   R   (   R   R   R>   Rf   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRm     s    	c         C   s?   t  d |  } y |  j d | j  Wn t k
 r: t SXt S(   s   
        Verify a signed tag

        @param tag: the tag's name
        @type tag: C{str}
        @return: Whether the signature on the tag could be verified
        @rtype: C{bool}
        s   -vR   (   R   RO   R>   R   R    R   (   R   R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   verify_tag  s    	c         C   s   t  j |  s! |  j |  } n  |  j rS d |  j   } |  j d | | g  n? d g } | rr | d g 7} n  | | d g 7} |  j d |  d S(   s   
        Force HEAD to a specific commit

        @param commit: commit to move HEAD to
        @param hard: also update the working copy
        @type hard: C{bool}
        s   refs/heads/%ss
   update-refs   --quiets   --hards   --t   resetN(   R   t   is_sha1Rr   Rl   Ro   RO   (   R   R   t   hardR|   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   force_head  s    		c         C   sj   t    } | j | d  | j | d  |  j d | j d i d d 6\ } } | rf t d   n  | S(   Ns   -unos   --porcelaint   statusR.   RQ   RR   s   Can't get repository status(   R   Rv   RB   R>   R   (   R   t	   porcelaint   ignore_untrackedR>   R#   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _status  s    			c         C   sj   |  j  r t d f S|  j d t d |  } | r\ |  j d t d |  } t d j |  f St d f Sd S(   sn  
        Does the repository contain any uncommitted modifications?

        @param ignore_untracked: whether to ignore untracked files when
            checking the repository status
        @type ignore_untracked: C{bool}
        @return: C{True} if the repository is clean, C{False} otherwise
            and Git's status message
        @rtype: C{tuple}
        R   R   R   N(   Rl   R   R   R    Rj   (   R   R   R#   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   is_clean  s    	
		c         C   s   t    } | j | d  | j | d  | j | d  |  j d | j d i d d 6\ } } } | r} t d |   n  d	 S(
   sb  
        Remove untracked files from the working tree.

        @param directories: remove untracked directories, too
        @type directories: C{bool}
        @param force: satisfy git configuration variable clean.requireForce
        @type force: C{bool}
        @param dry_run: don’t actually remove anything
        @type dry_run: C{bool}
        s   -ds   -fs   -nt   cleanR.   RQ   RR   s"   Can't execute repository clean: %sN(   R   Rv   R   R>   R   (   R   t   directoriest   forcet   dry_runt   optionst   _outR   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR      s    	c         C   s   |  j  r t St S(   s   
        Is the repository empty?

        @return: True if the repositorydoesn't have any commits,
            False otherwise
        @rtype: C{bool}
        (   Rp   R    R   (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   is_empty5  s    	i    c         C   sx   t  d d  } | j | d |  | j |  |  j d | j  \ } } | rd t d |   n  |  j | d |  S(   s  
        Find the SHA1 of a given name

        @param name: the name to look for
        @type name: C{str}
        @param short:  try to abbreviate SHA1 to given length
        @type short: C{int}
        @return: the name's sha1
        @rtype: C{str}
        s   --quiets   --verifys
   --short=%ds	   rev-parses   revision '%s' not foundi    (   R   R   Ry   RB   R>   R   R   (   R   R   t   shortR>   t   shaR%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRr   @  s    c         C   so   d } |  j    } | p | } t |  | k  sB t |  | k rk t d | | r[ d | n d f   n  | S(   s  
        Strip a given sha1 and check if the resulting
        hash has the expected length.

        >>> GitRepository.strip_sha1('  58ef37dbeb12c44b206b92f746385a6f61253c0a\n')
        '58ef37dbeb12c44b206b92f746385a6f61253c0a'
        >>> GitRepository.strip_sha1('58ef37d', 10)
        Traceback (most recent call last):
        ...
        GitRepositoryError: '58ef37d' is not a valid sha1 of length 10
        >>> GitRepository.strip_sha1('58ef37d', 7)
        '58ef37d'
        >>> GitRepository.strip_sha1('123456789', 7)
        '123456789'
        >>> GitRepository.strip_sha1('foobar')
        Traceback (most recent call last):
        ...
        GitRepositoryError: 'foobar' is not a valid sha1
        i(   s   '%s' is not a valid sha1%ss    of length %dR   (   R   R   R   (   R   t   lengtht   maxlent   st   l(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   S  s    $#c         C   s   |  j  d d | g  d S(   sr   
        Checkout treeish

        @param treeish: the treeish to check out
        @type treeish: C{str}
        R~   s   --quietN(   RO   (   R   t   treeish(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR~   s  s    c         C   s8   |  j  d | g d t \ } } } t t g | d k S(   s  
        Check if the repository has the treeish object I{treeish}.

        @param treeish: treeish object to look for
        @type treeish: C{str}
        @return: C{True} if the repository has that tree, C{False} otherwise
        @rtype: C{bool}
        s   ls-treeR   i    (   R   R   R    (   R   R   R   t   _errR%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   has_treeish|  s    	c         C   sj   | r i | d 6} n d } |  j d g  d | d t \ } } } | r` t d | d    n  | j   S(   s   
        Create a tree object from the current index

        @param index_file: alternate index file to read changes from
        @type index_file: C{str}
        @return: the new tree object's sha1
        @rtype: C{str}
        t   GIT_INDEX_FILEs
   write-treeR.   R   s!   Can't write out current index: %siN(   R*   R   R   R   R   (   R   t
   index_fileR.   t   treeRF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   write_tree  s    	c         C   s   d } t  d  } x: | D]2 } | \ } } } } | d | | | | f 7} q W|  j d | j | d t \ } }	 }
 |
 r t d |	   n  |  j |  S(   s   
        Create a tree based on contents. I{contents} has the same format than
        the I{GitRepository.list_tree} output.
        R   s   -zs   %s %s %s	%s t   mktreeR   s   Failed to mktree: '%s'(   R   R   R>   R   R   R   (   R   t   contentsR#   R>   t   objt   modet   typeR   R   R   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt	   make_tree  s    	c         C   sH   |  j  d d d | g \ } } | r: t d |   n  | d j   S(   s   
        Get type of a git repository object

        @param obj: repository object
        @type obj: C{str}
        @return: type of the repository object
        @rtype: C{str}
        s   cat-fileR>   s   -ts!   Not a Git repository object: '%s'i    (   RB   R   R   (   R   R   R#   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_obj_type  s    	!c   
      C   s   t  d  } | j | d  | j |  | j d  | j | |  |  j d | j d t \ } } } | r t d | | f   n  g  } x9 | j d  D]( }	 |	 r | j	 |	 j d	 d   q q W| S(
   s  
        Get a trees content. It returns a list of objects that match the
        'ls-tree' output: [ mode, type, sha1, path ].

        @param treeish: the treeish object to list
        @type treeish: C{str}
        @param recurse: whether to list the tree recursively
        @type recurse: C{bool}
        @return: the tree
        @rtype: C{list} of objects. See above.
        s   -zs   -rs   --s   ls-treeR   s   Failed to ls-tree '%s': '%s't    i   N(   R   Rv   Ry   R   R   R>   R   R   R\   R^   R*   (
   R   R   t   recurset   pathsR>   R#   R   R%   R   Rf   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt	   list_tree  s    $ c         C   s6   |  j  d | g  \ } } | r* t  n  | d d  S(   s   
        Gets the config value associated with I{name}

        @param name: config value to get
        @return: fetched config value
        @rtype: C{str}
        t   configi    i(   RB   R   (   R   R   t   valueR%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s     	c         C   s   y |  j  d  } Wn  t k
 r5 t j d  } n Xy |  j  d  } Wn  t k
 rk t j d  } n Xt j d |  } t j d |  } t | |  S(   s   
        Determine a sane values for author name and author email from git's
        config and environment variables.

        @return: name and email
        @rtype: L{GitModifier}
        s	   user.namet   USERs
   user.emailt   EMAILt   GIT_AUTHOR_EMAILt   GIT_AUTHOR_NAME(   R   R   R'   t   getenvR   (   R   R   t   email(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_author_info  s    c         C   s8  |  j  d g  d t \ } } } | r: t d |   n  i  } x | j   D] } |  j  d d d | g d t \ } } } | r t d | | f   n  d
 } g  } xo | j   D]a }	 t j d |	  }
 |
 r |
 j d  } n  t j d	 |	  }
 |
 r | j |
 j d   q q Wt	 | | |  | | <qM W| S(   s   
        Get a list of remote repositories

        @return: remote repositories
        @rtype: C{dict} of C{GitRemote}
        Rz   R   s!   Failed to get list of remotes: %st   shows   -ns+   Failed to get information for remote %s: %ss   \s*Fetch\s+URL:\s*(\S.*)i   s   \s*Push\s+URL:\s*(\S.*)N(
   R   R   R   RZ   R*   RX   R]   R`   R^   R
   (   R   R#   R   R%   t   remotesRz   t   _retR   R   Rf   R]   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_remotes   s*    !c         C   s0   |  j  d  d } g  | D] } | j   ^ q S(   s   
        Get all remote repositories

        @deprecated: Use get_remotes() instead

        @return: remote repositories
        @rtype: C{list} of C{str}
        Rz   i    (   RB   R   (   R   R#   Rz   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_remote_repos   s    	c         C   s   | |  j    k r t St Sd S(   s   
        Do we know about a remote named I{name}?

        @param name: name of the remote repository
        @type name: C{str}
        @return: C{True} if the remote repositore is known, C{False} otherwise
        @rtype: C{bool}
        N(   R   R   R    (   R   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   has_remote_repo,  s    	c         C   sS   t  d  } | j | d  | j | d  | j | |  |  j d | j  d S(   sj  
        Add a tracked remote repository

        @param name: the name to use for the remote
        @type name: C{str}
        @param url: the url to add
        @type url: C{str}
        @param tags: whether to fetch tags
        @type tags: C{bool}
        @param fetch: whether to fetch immediately from the remote side
        @type fetch: C{bool}
        Ry   s	   --no-tagss   --fetchRz   N(   R   t	   add_falseRv   Ry   RO   R>   (   R   R   R   Rn   t   fetchR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   add_remote_repo:  s
    c         C   s&   t  d |  } |  j d | j  d  S(   Nt   rmRz   (   R   RO   R>   (   R   R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   remove_remote_repoM  s    c         C   s   t  d  } | j | d  | j | d |  | rI | j | d  n  | j | |  | j | |  |  j d | j  d S(   s  
        Download objects and refs from another repository.

        @param repo: repository to fetch from
        @type repo: C{str}
        @param tags: whether to fetch all tag objects
        @type tags: C{bool}
        @param depth: deepen the history of (shallow) repository to depth I{depth}
        @type depth: C{int}
        @param refspec: refspec to use instead of the default from git config
        @type refspec: C{str}
        @param all_remotes: fetch all remotes
        @type all_remotes: C{bool}
        s   --quiets   --tagss
   --depth=%ss   --allR   N(   R   Rv   R   RO   R>   (   R   t   repoRn   t   deptht   refspect   all_remotesR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   Q  s    c         C   sY   t    } | j | d  | r2 | j | d  n | j | |  |  j d | j  d S(   s>  
        Fetch and merge from another repository

        @param repo: repository to fetch from
        @type repo: C{str}
        @param ff_only: only merge if this results in a fast forward merge
        @type ff_only: C{bool}
        @param all_remotes: fetch all remotes
        @type all_remotes: C{bool}
        s	   --ff-onlys   --allt   pullN(   R   Rv   RO   R>   (   R   R   t   ff_onlyR   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   l  s    	c   	      C   s   t    } | j | |  | j | d  | j | d  | d k r | } | rb | d | 7} n  | su d | } n  | j |  n  |  j d | j  d S(   sh  
        Push changes to the remote repo

        @param repo: repository to push to
        @type repo: C{str}
        @param src: the source ref to push
        @type src: C{str}
        @param dst: the name of the destination ref to push to
        @type dst: C{str}
        @param ff_only: only push if it's a fast forward update
        @type ff_only: C{bool}
        @param force: force push, can cause the remote repository to lose
        commits; use it with care
        @type force: C{bool}
        @param tags: push all refs under refs/tags, in addition to other refs
        @type tags: C{bool}
        s   -fs   --tagss   :%ss   +%st   pushN(   R   R   Rv   R*   Ry   RO   R>   (	   R   R   t   srct   dstR   R   Rn   R>   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s    	c         C   s)   t  | d |  } |  j d | j  d S(   s   
        Push a tag to the remote repo

        @param repo: repository to push to
        @type repo: C{str}
        @param tag: the name of the tag
        @type tag: C{str}
        R   R   N(   R   RO   R>   (   R   R   R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   push_tag  s    	c         C   sw   i  } t  | t  r! | g } n  | r0 d g n g  } | rI | | d <n  | r\ | | d <n  |  j d | | |  d S(   s[  
        Add files to a the repository

        @param paths: list of files to add
        @type paths: list or C{str}
        @param force: add files even if they would be ignored by .gitignore
        @type force: C{bool}
        @param index_file: alternative index file to use
        @param work_tree: alternative working tree to use
        s   -fR   t   GIT_WORK_TREERy   N(   R   R   RO   (   R   R   R   R   t	   work_treeR.   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt	   add_files  s    c         C   sH   t  | t  r | g } n  | r' g  n d g } |  j d | |  d S(   s   
        Remove files from the repository

        @param paths: list of files to remove
        @param paths: C{list} or C{str}
        @param verbose: be verbose
        @type verbose: C{bool}
        s   --quietR   N(   R   R   RO   (   R   R   R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   remove_files  s    	t   cachedc         C   s   d d d d d d d g } d g } x> | D]6 } | | k rQ | d	 | g 7} q+ t  d
 |   q+ W|  j d |  \ } } | r t  d |   n  | r g  | d j d  D] } | r | ^ q Sg  Sd S(   s   
        List files in index and working tree

        @param types: list of types to show
        @type types: C{list}
        @return: list of files
        @rtype: C{list} of C{str}
        R   t   deletedt   otherst   ignoredt   stageunmergedt   killedt   modifieds   -zs   --%ss   Unknown type '%s's   ls-filess   Error listing files: '%d'i    R   N(   R   RB   R\   (   R   t   typest	   all_typesR>   t   tR#   R%   t   file(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   list_files  s    		*c         C   s   t  d d d  } | j | d  | j |  |  j d | j d t \ } } } | sf |  j |  St d | | f   d S(	   s>  
        Hash a single file and write it into the object database

        @param filename: the filename to the content of the file to hash
        @type filename: C{str}
        @param filters: whether to run filters
        @type filters: C{bool}
        @return: the hash of the file
        @rtype: C{str}
        s   -ws   -tt   blobs   --no-filterss   hash-objectR   s   Failed to hash %s: %sN(   R   R   Ry   R   R>   R   R   R   (   R   t   filenamet   filtersR>   R   RF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   write_file  s    		c         C   s?   | r | j    n d  } |  j d d d | g | d | d  S(   NR   s   -qs   -mR.   (   t   get_author_envR*   RO   (   R   R   R>   t   author_infoR.   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   _commit  s    c         C   s<   t    } | j | d  |  j d | d | j d |  d S(   s@  
        Commit currently staged files to the repository

        @param msg: commit message
        @type msg: C{str}
        @param author_info: authorship information
        @type author_info: L{GitModifier}
        @param edit: whether to spawn an editor to edit the commit info
        @type edit: C{bool}
        s   --editR   R>   R  N(   R   Rv   R  R>   (   R   R   R  R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   commit_staged  s    	c         C   s?   t  d  } | j | d  |  j d | d | j d |  d S(   s   
        Commit all changes to the repository
        @param msg: commit message
        @type msg: C{str}
        @param author_info: authorship information
        @type author_info: L{GitModifier}
        s   -as   --editR   R>   R  N(   R   Rv   R  R>   (   R   R   R  R   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   commit_all!  s    c         C   s;   t  | t  r | g } n  |  j d | d | d |  d S(   s*  
        Commit the given files to the repository

        @param files: file or files to commit
        @type files: C{str} or C{list}
        @param msg: commit message
        @type msg: C{str}
        @param author_info: authorship information
        @type author_info: L{GitModifier}
        R   R>   R  N(   R   R   R  (   R   t   filesR   R  (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   commit_files-  s    c         C   s  t  j j |  j |  j d  } y t  j |  Wn t k
 rB n X|  j d d t d | d | |  j |  }	 | r y |  j	 |  }
 Wq t
 k
 r | r t j d |  d }
 q   q Xn d }
 d } g  } |
 r |
 g } n  | r-x< | D]1 } |  j	 |  } | | k r | | g 7} q q Wn  |  j d |	 d	 | d
 | d | d |  } | slt
 d   n  |  j d | | |
  | S(   s  
        Replace the current tip of branch I{branch} with the contents from I{unpack_dir}

        @param unpack_dir: content to add
        @type unpack_dir: C{str}
        @param msg: commit message to use
        @type msg: C{str}
        @param branch: branch to add the contents of unpack_dir to
        @type branch: C{str}
        @param other_parents: additional parents of this commit
        @type other_parents: C{list} of C{str}
        @param author: author information to use for commit
        @type author: C{dict} with keys I{name}, I{email}, I{date}
        @param committer: committer information to use for commit
        @type committer: C{dict} with keys I{name}, I{email}, I{date}
            or L{GitModifier}
        @param create_missing_branch: create I{branch} as detached branch if it
            doesn't already exist.
        @type create_missing_branch: C{bool}
        t	   gbp_indext   .R   R   R   s"   Will create missing branch '%s'...t   masterR   R   t   parentst   authort	   committers   Failed to commit trees   refs/heads/%sN(   R'   R   Rj   R"   t   unlinkt   OSErrorR   R   R   Rr   R   R5   R6   R*   t   commit_treeR   (   R   t
   unpack_dirR   Rp   t   other_parentsR  R  t   create_missing_brancht   git_index_fileR   t   curR  t   parentR   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt
   commit_dir<  s@    	
c         C   s   i  } x7 | j    D]) \ } } | r | | d | j   <q q Wx7 | j    D]) \ } } | rM | | d | j   <qM qM W| g }	 x | D] }
 |	 d |
 g 7}	 q W|  j d |	 | | d t \ } } } | s |  j |  St d |   d S(   s  
        Commit a tree with commit msg I{msg} and parents I{parents}

        @param tree: tree to commit
        @param msg: commit message
        @param parents: parents of this commit
        @param author: authorship information
        @type author: C{dict} with keys 'name' and 'email' or L{GitModifier}
        @param committer: comitter information
        @type committer: C{dict} with keys 'name' and 'email'
        s   GIT_AUTHOR_%ss   GIT_COMMITTER_%ss   -ps   commit-treeR   s   Failed to commit tree: %sN(   t   itemst   upperR   R   R   R   (   R   R   R   R  R  R  R.   t   keyt   valR>   R#  R   RF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR  z  s$    		c         C   s$  t  d  } | j | d |  | j | d  | rV | j d | | pK d f  n | rl | j |  n  | j | |  | j d  t | t  r | g } n  | j | |  |  j d | j  \ } }	 |	 r| r d | n d	 }
 t d
 | | |
 f   n  g  | D] } | j	   ^ qS(   s  
        Get commits from since to until touching paths

        @param since: commit to start from
        @type since: C{str}
        @param until: last commit to get
        @type until: C{str}
        @param paths: only list commits touching paths
        @type paths: C{list} of C{str}
        @param num: maximum number of commits to fetch
        @type num: C{int}
        @param options: list of additional options passed to git log
        @type  options: C{list} of C{str}ings
        @param first_parent: only follow first parent when seeing a
                             merge commit
        @type first_parent: C{bool}
        s   --pretty=format:%Hs   -%ds   --first-parents   %s..%sRq   s   --R5   s    on %sR   s   Error getting commits %s..%s%s(
   R   Rv   Ry   R   R   R   RB   R>   R   R   (   R   t   sincet   untilR   t   numt   first_parentR   R>   t   commitsR%   t   whereR   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_commits  s$     c         C   sP   |  j  d d | g d t \ } } } | rL t d | | j   f   n  | S(   s   git-show idR   s   --pretty=mediumR   s   can't get %s: %s(   R   R   R   t   rstrip(   R   t   idR   RF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR     s
    c         C   s   d g } | j  d |  | r0 | j  |  n  | j  d  |  j d | d t \ } } } | r t d | | d  f   n  | r g  | j d  d	 d	 d  D] } | j   ^ q Sg  Sd	 S(
   s   
        Get commmits matching I{regex}

        @param regex: regular expression
        @type regex: C{str}
        @param since: where to start grepping (e.g. a branch)
        @type since: C{str}
        s   --pretty=format:%Hs	   --grep=%ss   --R5   R   s   Error grepping log for %s: %sis   
N(   R^   R   R   R   R\   R   (   R   t   regexR)  R>   R2   RF   R%   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   grep_log  s    		3c         C   s   |  j  |  d S(   s   
        Gets the subject of a commit.

        @deprecated: Use get_commit_info directly

        @param commit: the commit to get the subject from
        @return: the commit's subject
        @rtype: C{str}
        t   subject(   t   get_commit_info(   R   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   get_subject  s    
c         C   s  |  j  d |  } t d d d d |  } |  j d | j  \ } } } | rb t d |   n  | j d  } t | d	 j   | d
 j   | d j    } t | d j   | d j   | d j    }	 t t	  }
 | d } | d	 d k r| j
 d	  n  xU t |  r^| d	 d k r^| j
 d	  j   } | j
 d	  } |
 | j |  q
Wi | d 6| d 6|	 d 6| d d 6| d d 6| d d 6|
 d 6S(   s  
        Look up data of a specific commit-ish. Dereferences given commit-ish
        to the commit it points to.

        @param commitish: the commit-ish to inspect
        @return: the commit's including id, author, email, subject and body
        @rtype: dict
        s   %s^0sL   --pretty=format:%an%x00%ae%x00%ad%x00%cn%x00%ce%x00%cd%x00%s%x00%f%x00%b%x00s   -zs
   --date=raws   --name-statusR   s%   Unable to retrieve commit info for %sR   i    i   i   i   i   i   i	   R   R1  R  R  i   R4  i   t	   patchnamei   t   bodyR  (   Rr   R   R   R>   R   R\   R   R   R    t   listt   popR   R^   (   R   R   t   commit_sha1R>   R#   R   R%   t   fieldsR  R  R  t   file_fieldsR   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR5    s:    	
 
c         C   s   t  d d d |  } | j | d  | j d | | r> d n d | f  | j | d | d	  |  j d
 | j  \ } }	 g  | D] }
 |
 j   ^ q S(   sw  
        Output the commits between start and end as patches in output_dir.

        This outputs the revisions I{start...end} by default. When using
        I{symmetric} to C{false} it uses I{start..end} instead.

        @param start: the commit on the left side of the revision range
        @param end: the commit on the right hand side of the revisino range
        @param output_dir: directory to write the patches to
        @param signature: whether to output a signature
        @param thread: whether to include In-Reply-To references
        @param symmetric: whether to use the symmetric difference (see above)
        s   -Ns   -ks   -os   --no-signatures   %s%s%ss   ...s   ..s   --thread=%ss   --no-threads   format-patch(   R   R   Ry   RB   R>   R   (   R   t   startt   endt
   output_dirt	   signaturet   threadt	   symmetricR   R?   R%   Rf   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   format_patches  s    	&c         C   s{   g  } | r | d | g 7} n  | r5 | j  d  n  | d k rZ | d t |  g 7} n  | j  |  |  j d |  d S(   s   Apply a patch using git applys   -Cs   --indexs   -pt   applyN(   R^   R*   t   strRO   (   R   t   patcht   indext   contextR   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   apply_patch7  s    c         C   s   t  d d  } | t k r+ | j d  n | rE | j d |  n  | j | d  | j | d  | j | d  | j |  | j | |  | r | j d |  n  |  j d	 | j  \ }	 }
 } | r t d
   n  |	 S(   s  
        Diff two git repository objects

        @param obj1: first object
        @type obj1: C{str}
        @param obj2: second object
        @type obj2: C{str}
        @param paths: List of paths to diff
        @type paths: C{list}
        @param stat: Show diffstat
        @type stat: C{bool} or C{int} or C{str}
        @param summary: Show diffstat
        @type summary: C{bool}
        @param text: Generate textual diffs, treat all files as text
        @type text: C{bool}
        @param ignore_submodules: ignore changes to submodules
        @type ignore_submodules: C{bool}
        @return: diff
        @rtype: C{str}
        s   -ps   --no-ext-diffs   --stats	   --stat=%ss	   --summarys   --texts   --ignore-submodules=alls   --t   diffs   Git diff failed(   R   R   Ry   Rv   R   R>   R   (   R   t   obj1t   obj2R   t   statt   summaryt   textt   ignore_submodulesR   R?   RF   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRK  C  s     c   	      K   sV   d | d | d | | g } |  j  d | |  \ } } | rR t d |   n  d S(   s  
        Create an archive from a treeish

        @param format: the type of archive to create, e.g. 'tar.gz'
        @type format: C{str}
        @param prefix: prefix to prepend to each filename in the archive
        @type prefix: C{str}
        @param output: the name of the archive to create
        @type output: C{str}
        @param treeish: the treeish to create the archive from
        @type treeish: C{str}
        @param kwargs: additional commandline options passed to git-archive
        s   --format=%ss   --prefix=%ss   --output=%st   archives   Unable to archive %sN(   RB   R   (	   R   t   formatRU   R?   R   t   kwargsR>   R#   R%   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRR  k  s
    c         C   s)   | r d g n g  } |  j  d |  d S(   s   
        Cleanup unnecessary files and optimize the local repository

        param auto: only cleanup if required
        param auto: C{bool}
        s   --autot   gcN(   RO   (   R   t   autoR>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   collect_garbage  s    c         C   s0   t  j j t  j j |  j d   r( t St Sd S(   s   
        Does the repo have any submodules?

        @return: C{True} if the repository has any submodules, C{False}
            otherwise
        @rtype: C{bool}
        s   .gitmodulesN(   R'   R   t   existsRj   R   R    (   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   has_submodules  s    $c         C   s   |  j  d d | g  d S(   sn   
        Add a submodule

        @param repo_path: path to submodule
        @type repo_path: C{str}
        t	   submoduleRy   N(   RO   (   R   t	   repo_path(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   add_submodule  s    c         C   so   |  j    s d Sd g } | r/ | j d  n  | rE | j d  n  | s[ | j d  n  |  j d |  d S(   s>  
        Update all submodules

        @param init: whether to initialize the submodule if necessary
        @type init: C{bool}
        @param recursive: whether to update submodules recursively
        @type recursive: C{bool}
        @param fetch: whether to fetch new objects
        @type fetch: C{bool}
        NR-   s   --recursives   --inits
   --no-fetchRZ  (   RY  R^   RO   (   R   t   initt	   recursiveR   R>   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   update_submodules  s    	c         C   s	  g  } | d k r |  j } n  | g } | r= | d g 7} n  |  j d | d | \ } } x | D] } | d  j d d  \ }	 }
 } } |
 d k rb t j j | |  } | j | j |  j d  j d  | f  | r| |  j	 | d	 | d
 | 7} qqb qb W| S(   s   
        List the submodules of treeish

        @return: a list of submodule/commit-id tuples
        @rtype: list of tuples
        s   -rs   ls-treeR3   ii   R   R   t   /R   R^  N(
   R*   R   RB   R\   R'   Rj   R^   R   t   lstript   get_submodules(   R   R   R   R^  t
   submodulesR>   R#   R%   Rf   R   t   objtypeR   R   t   nextpath(    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRb    s"    
	"!
c         C   s  t    } t j j |  } | j | d  | r7 d n d } yt j j |  sb t j |  n  y@ |  j d d d | j d d d d d	 | d
 t
  \ } } }	 Wn# t k
 r }
 t d |
   n X|	 r t d |   n  | rAt t j j | | d  d  4 } | | d d k r$d n d 7} | j |  Wd QXn  |  |  SWn- t k
 r{} t d | | d f   n Xd S(   s  
        Create a repository at path

        @param path: where to create the repository
        @type path: C{str}
        @param bare: whether to create a bare repository
        @type bare: C{bool}
        @return: git repository object
        @rtype: L{GitRepository}
        s   --bareR   s   .gitR=   R]  R>   RD   R.   R3   R   s   Error running git init: %st   descriptiont   wis   
Ns(   Cannot create Git repository at '%s': %si   (   R   R'   R   R(   Rv   RX  t   makedirsRC   R>   R*   R   RM   R   t   openRj   t   writeR  (   t   klassR   Rf  Rl   R>   R(   Rk   R2   RF   R%   RN   t   fR   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   create  s6    		$ c         C   s7  t  j j |  } | r! d }	 n | j d d  \ } }	 t d  }
 |
 j | d |  |
 j | d  |
 j | d  |
 j | d  |
 j |  |
 j |	 |	  y[t  j j |  s t  j	 |  n  y@ |  j
 d d	 d
 |
 j d d d d d | d t  \ } } } Wn# t k
 r/} t d |   n X| rIt d |   n  |	 sy# | j d  j d d  d }	 Wn' t k
 r| j d d  d }	 n X| s| r|	 j d  sd |	 }	 qq|	 j d  r|	 d  }	 qn  |  t  j j | |	   SWn0 t k
 r2} t d | | | d f   n Xd S(   s>  
        Clone a git repository at I{remote} to I{path}.

        @param path: where to clone the repository to
        @type path: C{str}
        @param remote: URL to clone
        @type remote: C{str}
        @param depth: create a shallow clone of depth I{depth}
        @type depth: C{int}
        @param recursive: whether to clone submodules
        @type recursive: C{bool}
        @param mirror: whether to pass --mirror to git-clone
        @type mirror: C{bool}
        @param bare: whether to create a bare repository
        @type bare: C{bool}
        @param auto_name: If I{True} create a directory below I{path} based on
            the I{remote}s name. Otherwise create the repo directly at I{path}.
        @type auto_name: C{bool}
        @return: git repository object
        @rtype: L{GitRepository}
        R`  i   s   --quiets   --depths   --recursives   --mirrors   --bareR=   t   cloneR>   RD   R.   R3   R   s   Error running git clone: %st   :s   .gits   %s.gitis,   Cannot clone Git repository '%s' to '%s': %sN(   R'   R   R(   R*   t   rsplitR   Rv   Ry   RX  Rh  RC   R>   R   RM   R   R0  t
   IndexErrorR\   t   endswithRj   R  (   Rk  R   Rz   R   R^  t   mirrorRl   t	   auto_nameR(   R   R>   R2   RF   R%   RN   R   (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyRn    sP    		#N(b   R   R   R	   R&   R   t   staticmethodR4   R*   RB   R    R   t   classmethodRC   RO   Ri   R   R   Rk   Rl   Rn   Rp   Rs   Ru   Rx   R{   Ro   R}   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   Rm   R   R   R   R   R   R   Rr   R   R~   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R	  R  R  R  R  R  R$  R  R/  R   R3  R6  R5  RD  RJ  RK  RR  RW  RY  R\  R_  Rb  Rm  Rn  (    (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyR   B   s   	
				,	
						
					
			+											 			"	=#&			-'			
!*	(   R	   R7   t   os.pathR'   RX   t   collectionsR    t   gbp.logR5   t
   gbp.errorsR   t   gbp.git.modifierR   t   gbp.git.commitR   t   gbp.git.errorsR   t   gbp.git.argsR   R   t   objectR
   R   (    (    (    s6   /usr/lib/python2.7/dist-packages/gbp/git/repository.pyt   <module>   s   