U
    &]^p:                     @   sb  d Z ddlmZmZ ddlZddlZddlZddlZz0ddl	m
Z
mZmZmZmZmZmZmZmZ W n ek
rx   Y nX ddlmZmZmZ ddlmZ ddlmZ dZd	Zd
dddgZdZdddddgZ dZ!dZ"dZ#dZ$G dd deZ%G dd de&Z'G dd de'Z(G dd de'Z)G d d! d!eZ*e+d"kr^e*ej,d# d$Z-e-j./ Z/e0e/1d dS )%zX Representation of Debian binary package (.deb) files


Debfile Classes
===============
    )absolute_importprint_functionN)	AnyDictIOIteratorListOptionalTextTypeVarUnion)ArFileArErrorArMember)	Changelog)Deb822zdata.tarzcontrol.targzbz2xzZlzmazdebian-binaryZpreinstZpostinstZprermZpostrmZconfigcontrolzusr/share/doc/%s/changelog.gzz$usr/share/doc/%s/changelog.Debian.gzmd5sumsc                   @   s   e Zd ZdS )DebErrorN__name__
__module____qualname__ r   r   0/usr/lib/python3/dist-packages/debian/debfile.pyr   A   s   r   c                   @   sz   e Zd ZdZdd Zdd Zedd Zdd	 ZdddZ	dddZ
dd Zdd Zejdk rfdd Zdd Zdd Zd
S )DebParta  'Part' of a .deb binary package.

    A .deb package is considered as made of 2 parts: a 'data' part
    (corresponding to the possibly compressed 'data.tar' archive embedded
    in a .deb) and a 'control' part (the 'control.tar.gz' archive). Each of
    them is represented by an instance of this class. Each archive should
    be a compressed tar archive although an uncompressed data.tar is permitted;
    supported compression formats are: .tar.gz, .tar.bz2, .tar.xz .

    When referring to file members of the underlying .tar.gz archive, file
    names can be specified in one of 3 formats "file", "./file", "/file". In
    all cases the file is considered relative to the root of the archive. For
    the control part the preferred mechanism is the first one (as in
    deb.control.get_content('control') ); for the data part the preferred
    mechanism is the third one (as in deb.data.get_file('/etc/vim/vimrc') ).
    c                 C   s   || _ d | _d S N)_DebPart__member_DebPart__tgz)selfmemberr   r   r   __init__W   s    zDebPart.__init__c           	   
      sp  | j dkrj| jj}tj|d dd }|tksF|tksF|tkr^t	j
dk r|dkrz@ddl}ddl ddl}|jddg|j|jd fd	d
d}W n2 ttfk
r } ztd| W 5 d}~X Y nX || j d }|jdkrtd|j ||}n| j}ztj|dd| _ W n8 tjtjfk
rZ } ztd| W 5 d}~X Y nX ntd| | j S )zReturn a TarFile object corresponding to this part of a .deb
        package.

        Despite the name, this method gives access to various kind of
        compressed tar archives, not only gzipped ones.
        N   )   r&   r   r   Zunxzz--stdoutFc                      s      j jS r   )signalSIGPIPESIG_DFLr   r'   r   r   <lambda>u   s    zDebPart.tgz.<locals>.<lambda>)stdinstdoutZuniversal_newlinesZ
preexec_fnz%sz!command has failed with code '%s'zr:*)fileobjmodez#tarfile has returned an error: '%s'z"part '%s' has unexpected extension)r!   r    nameospathsplitext	PART_EXTS	DATA_PART	CTRL_PARTsysversion_info
subprocessr'   ioPopenPIPEOSError
ValueErrorr   Zcommunicateread
returncodeBytesIOtarfileopenZ	ReadErrorZCompressionError)	r"   r0   	extensionr9   r:   procedatabufferr   r*   r   tgz\   s>    	 


 zDebPart.tgzc                 C   s2   |  dr| dd } n|  dr.| dd } | S )zw try (not so hard) to obtain a member file name in a form relative
        to the .tar.gz root and with no heading '.' ./   N/r%   )
startswith)fnamer   r   r   Z__normalize_member   s
    

zDebPart.__normalize_memberc                 C   s*   t |}|   }d| |kp(||kS )z.Check if this part contains a given file name.rJ   )r   _DebPart__normalize_memberrI   getnames)r"   rN   namesr   r   r   has_file   s
    
zDebPart.has_fileNc                 C   s   t |}z|  d| }W n" tk
rB   |  |}Y nX |dkrTtd|dk	rtjdkrddl}t	|dsdd |_
|j|||d	S ddl}|dkrd
}|j|||dS |S )zReturn a file object corresponding to a given file name.

        If encoding is given, then the file object will return Unicode data;
        otherwise, it will return binary data.
        rJ   NzFile not found inside package3r   flushc                   S   s   d S r   r   r   r   r   r   r+          z"DebPart.get_file.<locals>.<lambda>encodingerrorsstrict)rX   )r   rO   rI   ZextractfileKeyErrorr   r7   versionr:   hasattrrT   TextIOWrappercodecsEncodedFile)r"   rN   rW   rX   Zfobjr:   r^   r   r   r   get_file   s$    



zDebPart.get_filec                 C   s,   | j |||d}d}|r(| }|  |S )zReturn the string content of a given file, or None (e.g. for
        directories).

        If encoding is given, then the content will be a Unicode object;
        otherwise, it will contain binary data.
        rV   N)r`   r?   close)r"   rN   rW   rX   fZcontentr   r   r   get_content   s    zDebPart.get_contentc                 C   s   t |   S r   )iterrI   rP   r"   r   r   r   __iter__   s    zDebPart.__iter__c                 C   s
   |  |S r   rR   r"   rN   r   r   r   __contains__   s    zDebPart.__contains__rS   c                 C   s
   |  |S r   rg   rh   r   r   r   has_key   s    zDebPart.has_keyc                 C   s
   |  |S r   )rc   rh   r   r   r   __getitem__   s    zDebPart.__getitem__c                 C   s   | j   d S r   )r    ra   re   r   r   r   ra      s    zDebPart.close)NN)NN)r   r   r   __doc__r$   rI   staticmethodrO   rR   r`   rc   rf   ri   r7   r[   rj   rk   ra   r   r   r   r   r   E   s    0
	
!  

r   c                   @   s   e Zd ZdS )DebDataNr   r   r   r   r   rn      s   rn   c                   @   s&   e Zd Zdd Zdd ZdddZdS )	
DebControlc                 C   s*   i }t D ]}| |r| |||< q|S )zo Return a dictionary of maintainer scripts (postinst, prerm, ...)
        mapping script names to script text. )MAINT_SCRIPTSrR   rc   )r"   scriptsrN   r   r   r   rq      s
    
zDebControl.scriptsc                 C   s   t | tS )z Return the debian/control as a Deb822 (a Debian-specific dict-like
        class) object.

        For a string representation of debian/control try
        .get_content('control') )r   rc   CONTROL_FILEre   r   r   r   
debcontrol  s    zDebControl.debcontrolNc           	      C   s   |  tstdt | jt||d}i }d}|dkr:d}| D ]D}||dd\}}tjdkr~t	|t
r~| ||< qB|||< qB|  |S )a   Return a dictionary mapping filenames (of the data part) to
        md5sums. Fails if the control part does not contain a 'md5sum' file.

        Keys of the returned dictionary are the left-hand side values of lines
        in the md5sums member of control.tar.gz, usually file names relative to
        the file system root (without heading '/' or './').

        The returned keys are Unicode objects if an encoding is specified,
        otherwise binary. The returned values are always Unicode.z('%s' file not found, can't list MD5 sumsrV   z
Ns   
r%   rS   )rR   MD5_FILEr   r`   	readlinesrstripsplitr7   r[   
isinstancebytesdecodera   )	r"   rW   rX   Zmd5_fileZsumsnewlinelineZmd5rN   r   r   r   r     s     

zDebControl.md5sums)NN)r   r   r   rq   rs   r   r   r   r   r   ro      s   
ro   c                   @   sp   e Zd ZdZdddZdd Zedd	 Zed
d	 Zedd	 Z	dd Z
dd ZdddZdd Zdd ZdS )DebFilea  Representation of a .deb file (a Debian binary package)

    DebFile objects have the following (read-only) properties:
        - version       debian .deb file format version (not related with the
                        contained package version), 2.0 at the time of writing
                        for all .deb packages in the Debian archive
        - data          DebPart object corresponding to the data.tar.gz (or
                        other compressed or uncompressed tar) archive contained
                        in the .deb file
        - control       DebPart object corresponding to the control.tar.gz (or
                        other compressed tar) archive contained in the .deb
                        file
    Nrc                    s   t | ||| t|    fdd}t kr<tdt i | _t| |t	| jt	< t
| |t| jt< d | _| t}|  | _|  d S )Nc                    sr    fddt D } ttfkr(|  t|}|sHtd| n&t|dkrbtd| nt|d S d S )Nc                    s   g | ]}d  |f qS )z%s.%sr   ).0Zextbasenamer   r   
<listcomp>H  s     zBDebFile.__init__.<locals>.compressed_part_name.<locals>.<listcomp>z9missing required part in given .deb (expected one of: %s)r%   z>too many parts in given .deb (was looking for only one of: %s)r   )	r4   r5   r6   appendintersectionsetr   lenlist)r   Z
candidatespartsZactual_namesr   r   compressed_part_nameF  s"    
z.DebFile.__init__.<locals>.compressed_part_namez4missing required part in given .deb (expected: '%s'))r   r$   r   rP   	INFO_PARTr   _DebFile__partsro   	getmemberr6   rn   r5   _DebFile__pkgnamer?   strip_DebFile__versionra   )r"   filenamer/   r.   r   rb   r   r   r   r$   A  s(    
zDebFile.__init__c                 C   s   |   d | _d S )Npackage)rs   r   re   r   r   r   Z__updatePkgNameh  s    zDebFile.__updatePkgNamec                 C   s   | j S r   )r   re   r   r   r   r+   k  rU   zDebFile.<lambda>c                 C   s
   | j t S r   )r   r5   re   r   r   r   r+   l  rU   c                 C   s
   | j t S r   )r   r6   re   r   r   r   r+   m  rU   c                 C   s
   | j  S )z See .control.debcontrol() )r   rs   re   r   r   r   rs   q  s    zDebFile.debcontrolc                 C   s
   | j  S )z See .control.scripts() )r   rq   re   r   r   r   rq   v  s    zDebFile.scriptsc                 C   s   | j j||dS )z See .control.md5sums() rV   )r   r   )r"   rW   rX   r   r   r   r   {  s    zDebFile.md5sumsc                 C   sl   | j dkr|   t| j  t| j  fD ]@}| j|r&tj| j|d}|	 }|
  t|  S q&dS )z Return a Changelog object for the changelog.Debian.gz of the
        present .deb package. Return None if no changelog can be found. N)r.   )r   _DebFile__updatePkgNameCHANGELOG_DEBIANCHANGELOG_NATIVErG   rR   gzipZGzipFiler`   r?   ra   r   )r"   rN   r   Zraw_changelogr   r   r   	changelog  s    
zDebFile.changelogc                 C   s   | j   | j  d S r   )r   ra   rG   re   r   r   r   ra     s    
zDebFile.close)Nr~   N)NN)r   r   r   rl   r$   r   propertyr[   rG   r   rs   rq   r   r   ra   r   r   r   r   r}   1  s   
'
r}   __main__r%   )r   )2rl   Z
__future__r   r   r   rB   r7   os.pathr1   typingr   r   r   r   r   r	   r
   r   r   ImportErrorZdebian.arfiler   r   r   Zdebian.changelogr   Zdebian.deb822r   r5   r6   r4   r   rp   rr   r   r   rt   r   objectr   rn   ro   r}   r   argvZdebr   rI   printr   r   r   r   r   <module>   s>   0 .:f

