o
    U7eW                     @   s   d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ e   G dd dej	Z	G dd de	Z
G d	d
 d
ejZG dd deZdS )    N)copy)sourceslist)
get_distroc                   @   s   e Zd ZdZedd Ze									dddZdd Zed	d
 Z	e	j
dd
 Z	edd Zedd Zej
dd Zdd Zdd Zdd Zdd ZdS )SourceEntryz single sources.list entry c                 K   s   | | j di |S )N )create_line)clskwargsr   r   H/usr/lib/python3/dist-packages/softwareproperties/extendedsourceslist.pycreate_entry   s   zSourceEntry.create_entryNc              	   C   s\  |du rd}|du rt  j}|du rt  j}|du rg }|du r"g }|dr.d}|d}|r2dnd}g }|rC|dd|  |	durS|d	|	rNd
nd  d|}|r`d| d}|sd|}|rt|dd }| d| }d|}|rd| }|
r|
dsd|
 }
n|
dsd|
 }
nd}
| | | d| d| | |
 	 S )aj   Create a line from the given parts.

        The 'uri' parameter is mandatory; the rest will be filled with defaults
        if not set or if set to None.

        If 'dist' and 'suite' are both provided, 'suite' is ignored. If 'dist'
        includes a pocket and 'pocket' is provided, the 'pocket' parameter
        will replace the pocket in 'dist'.
        NF#Tz#  zarch=,ztrusted=yesno z []-r   z #)	r   binary_typecodename
startswithlstripappendjoin	partitionstrip)r   uridisabledtypedistsuitepocketcompsarchitecturestrustedcommenthashmarkoptionsr   r   r
   r      sL   







(zSourceEntry.create_linec                 C   s   zR| j s|j r| j |j ko| j|jkW S | j|jkoQ| j|jkoQt| jt|jkoQ| j|jkoQ| jd|jdkoQ| j	|j	koQ| j
|j
koQt| jt|jkW S  ty\   Y dS w )- equal operator for two sources.list entries /F)invalidliner   r   setr#   r$   r   rstripr    r!   r"   AttributeErrorselfotherr   r   r
   __eq___   s.   




zSourceEntry.__eq__c                 C   s   | j dd  S )z_ Return the suite, without pocket

        This always returns the suite in lowercase.
        r   r   )r   r   lowerr0   r   r   r
   r    p   s   zSourceEntry.suitec                 C   s0   |sd S | j }|r| d| | _d S || _d S Nr   )_pocketr   )r0   	new_suiter!   r   r   r
   r    x   s   
c                 C   s   | j dd S )z, Return the pocket, or if unset return None r      )r   r   r4   r   r   r
   r6      s   zSourceEntry._pocketc                 C   s   | j pd S )zo Return the pocket, or if unset return 'release'

        This always returns the pocket in lowercase.
        release)r6   r3   r4   r   r   r
   r!      s   zSourceEntry.pocketc                 C   s&   |r| j  d| | _d S | j | _d S r5   )r    r   )r0   
new_pocketr   r   r
   r!      s   c                 C   s   t t| | jdS )z Copy this SourceEntry file)r   strr<   r4   r   r   r
   __copy__   s   zSourceEntry.__copy__c                 K   s*   t | }| D ]
\}}t||| q|S )z8 Return copy of this SourceEntry with replaced field(s) )r   itemssetattr)r0   r	   entrykvr   r   r
   _replace   s   zSourceEntry._replacec                 C   s   |    S )z debug helper )r=   r   r4   r   r   r
   __str__   s   zSourceEntry.__str__c                 C   sD   | j r| jS | j| j| j| j| j| j| j| j	| j
| jd	}| dS )z$ return the current entry as string )	r   r   r   r    r!   r"   r#   r$   r%   
)r*   r+   r   r   r   r   r    r6   r"   r#   r$   r%   )r0   r+   r   r   r
   r=      s   
zSourceEntry.str)	NNNNNNNNN)__name__
__module____qualname____doc__classmethodr   r   r2   propertyr    setterr6   r!   r>   rD   rE   r=   r   r   r   r
   r      s<    
B

	


r   c                       sl   e Zd ZdZ fddZdd Zdd Zdd	d
Zedd Z	e	j
dd Z	 fddZ fddZ  ZS )MergedSourceEntryau   A SourceEntry representing one or more identical SourceEntries

    The SourceEntries this represents are identical except for the components
    they contain.  This will contain all the contained entries' components.

    If all components are removed, this will still act as a normal SourceEntry
    without any components, but all corresponding real SourceEntries will be
    removed from the SourcesList.

    This may contain multiple SourceEntries that overlap components (e.g.
    two entries that both contain 'main' component), however once any
    changes are made to the set of comps, duplicates will be removed.
    c                    s8   d| _ tt| jt||jd d| _ || _|g| _d S )NFr;   T)_initializedsuperrN   __init__r=   r<   _sourceslist_entries)r0   rA   r   	__class__r   r
   rQ      s
   zMergedSourceEntry.__init__c                 C   s0   t |tsdS | jrdS | jg d|jg dkS )z1 Check if this is equal to other, ignoring comps Fr"   )
isinstancer   r*   rD   r/   r   r   r
   match   s
   
zMergedSourceEntry.matchc                 C   s   | j | dS )a   Append entry

        This should be called only with an entry that is equal to us,
        besides comps.  The new entry may contain comps already in
        other entries we contain, but any modification of our comps
        will remove all duplicate comps.
        N)rS   r   r0   rA   r   r   r
   _append   s   zMergedSourceEntry._appendFc                 C   s  t t|}t | j|ks|sdS | jD ]&}t |j|@ r:|t |j8 }tt | j| | _tt |j|B |_ nqtt | j|B | _z| jd }W n
 tyV   Y dS w |r|rt |j|kr|jtt |j| d}t||_| jj|d }| jj	|| | 
| |S )a]   Get single SourceEntry with comps

        This moves all the components into a single entry in our entries
        list, and returns that entry.

        If add is False, this will return None if we do not already
        contain all the requested comps; otherwise this adds any
        new comps.

        If isolate is False, the entry returned may contain more
        components than those requested in comps.  If isolate is True,
        this moves any excess components into a new entry, located
        immediately after the returned entry.

        If any of the components already exist in one of our entries,
        it is used to move all the components to; otherwise the first
        entry in our list is used.

        Any of our entries that has all its components moved (thus has
        no components left) will be removed from our entries list and
        removed from our sourceslist.

        If called with no comps this will return our first SourceEntry.
        If we contain no SourceEntries (because we contain no components),
        this will return None if called with no comps.
        Nr   rV      )r,   r   r"   rS   listKeyErrorrD   rR   indexinsertrZ   )r0   r"   addisolateenewenewir   r   r
   	get_entry   s.   


zMergedSourceEntry.get_entryc                 C   s(   t  }| jD ]	}|t |jO }qt|S N)r,   rS   r"   r\   )r0   crb   r   r   r
   r"     s   
zMergedSourceEntry.compsc                 C   s   | j sd S tt|}|t| jkrd S | jD ]}tt|j|@ |_|t|j8 }q|rP| js@t| g| _| jj| jd  tt| jd j|B | jd _t| jD ]}|jsg| j| | jj| qUd S )Nr   )	rO   r,   r   r"   rS   r\   rR   r   remove)r0   r"   rb   r   r   r
   r"     s&   
 c                    s*   | j D ]}|| qtt| | d S rf   )rS   set_enabledrP   rN   )r0   enabledrb   rT   r   r
   ri   7  s   
zMergedSourceEntry.set_enabledc                    s@   |dks| ds| jD ]}t||| qtt| || d S )Nr"   _)r   rS   r@   rP   rN   __setattribute__)r0   namevaluerb   rT   r   r
   rl   <  s   
z"MergedSourceEntry.__setattribute__)FF)rG   rH   rI   rJ   rQ   rX   rZ   re   rL   r"   rM   ri   rl   __classcell__r   r   rT   r
   rN      s    


=

rN   c                       sf   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdddg dfddZ	dd Z
dddZ  ZS )SourcesListz8 represents the full sources.list + sources.list.d file c                    s   t  | _tt|   dS )z" update the list of known entries N)r,   _filesrP   rp   refreshr4   rT   r   r
   rr   F  s   zSourcesList.refreshc                    4   t | j }| D ]\  fdd|D }q	|S )) convenience method to get filtered list c                    "   g | ]}t |  kr|qS r   getattr.0rb   keyrn   r   r
   
<listcomp>O     " z&SourcesList.filter.<locals>.<listcomp>r\   r?   r0   r	   lr   rz   r
   filterK     
zSourcesList.filterc                 c       | j D ]}|V  qdS )zM simple iterator to go over self.list, returns SourceEntry
            types Nr\   rY   r   r   r
   __iter__R  s   
zSourcesList.__iter__c                 C   
   t | jS z calculate len of self.list lenr\   r4   r   r   r
   __len__X     
zSourcesList.__len__c                    ,   t  fddD ot fdd D S )r(   c                       g | ]}| v qS r   r   rx   r1   r   r
   r|   ^      z&SourcesList.__eq__.<locals>.<listcomp>c                    r   r   r   rx   r4   r   r
   r|   _  r   allr/   r   r1   r0   r
   r2   \     zSourcesList.__eq__r   NFc
              	   C   s`   |dkr|t | jk r| j| }
nd}
tj|	||||||d}t||d}t| }|j||
dS )z+ Create a new entry and add it to our list r   N)r   r   r   r   r"   r%   r#   r;   )before)r   r\   r   r   CollapsedSourcesList	add_entry)r0   r   r   r   r"   r%   posr<   r#   r   r   r+   	new_entry	collapsedr   r   r
   r`   a  s   
zSourcesList.addc                 C   s   z.t |d}|D ]}t||}| j| q	W d   n1 s!w   Y  | j| W dS  ty?   td|  Y dS w )z (re)load the current sources rNzcould not open file '%s'
)	openr   r\   r   rq   r`   	Exceptionloggingwarning)r0   r<   fr+   sourcer   r   r
   loadp  s   
zSourcesList.loadc              
      s  t dd | jD }|D ]+ t d} fdd| jD D ]	}||  qW d   n1 s2w   Y  q|rW| j| D ] zt  W q? tt	fyS   Y q?w || _t
jd}||vrd}t|d}|| W d   dS 1 syw   Y  dS dS )	a*   save the current sources

        By default, this will NOT remove any files that we no longer
        have entries for; those files will not be modified at all.

        If 'remove' is True, any files that we initially parsed, but
        no longer have any entries for, will be removed.
        c                 s   s    | ]}|j V  qd S rf   r;   rx   r   r   r
   	<genexpr>  s    z#SourcesList.save.<locals>.<genexpr>wc                    s   g | ]	}|j  kr|qS r   r;   )ry   sfilenamer   r
   r|     s    z$SourcesList.save.<locals>.<listcomp>NzDir::Etc::sourcelistz## See sources.list(5) for more information, especialy
# Remember that you can only use http, ftp or file URIs
# CDROMs are managed through the apt-cdrom tool.
)r,   r\   r   writer=   rq   osrh   OSErrorIOErrorapt_pkgconfig	find_file)r0   rh   filesr   r   
sourcelistheaderr   r   r
   save{  s0   	"zSourcesList.save)F)rG   rH   rI   rJ   rr   r   r   r   r2   r`   r   r   ro   r   r   rT   r
   rp   C  s    
rp   c                   @   st   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dZdd Zdd Zdd Zdd ZdS )r   a]   collapsed version of SourcesList

    This provides a 'collapsed' view of a SourcesList.
    Each entry in our list is a MergedSourceEntry, representing real
    SourceEntry(s) from our backing SourcesList.

    Any changes to our MergedSourceEntries are reflected in our
    backing SourcesList, however direct changes to SourceEntries
    in our backing SourcesList are not reflected in our list until
    after our refresh() method is called.

    If you change any part of any MergedSourceEntry besides the comps,
    you must refresh the CollapsedSourcesList to pick up those changes.

    The 'files' kwarg may be used to restrict which lines of the backing
    SourcesList are included, by providing a list of filenames. This
    can be used, for example, to get a CollapsedSourcesList of only
    SourceEntry lines from the main sources.list file.
    Nc                C   s$   |pt  | _|| _g | _|   d S rf   )rp   r   rq   r\   rr   )r0   r   r   r   r   r
   rQ     s   zCollapsedSourcesList.__init__c                 c   r   )zK iterator for self.list

        Returns MergedSourceEntry objects
        Nr   rY   r   r   r
   r     s   
zCollapsedSourcesList.__iter__c                 C   r   r   r   r4   r   r   r
   r     r   zCollapsedSourcesList.__len__c                    r   )r(   c                    r   r   r   rx   r   r   r
   r|     r   z/CollapsedSourcesList.__eq__.<locals>.<listcomp>c                    r   r   r   rx   r4   r   r
   r|     r   r   r/   r   r   r
   r2     r   zCollapsedSourcesList.__eq__c                 C   s
   |  |S )z* check if other is contained in this list )	has_entryr/   r   r   r
   __contains__  r   z!CollapsedSourcesList.__contains__c                    rs   )rt   c                    ru   r   rv   rx   rz   r   r
   r|     r}   z/CollapsedSourcesList.filter.<locals>.<listcomp>r~   r   r   rz   r
   r     r   zCollapsedSourcesList.filterc                 C   sb   g | _ | jD ](}| jr|j| jvrq| j D ]}||r#||  nq| j t|| j qdS )a-   update only our list of MergedSourceEntries

        This updates only our list of MergedSourceEntries, our backing
        SourcesList is not updated.  This should be called anytime
        our backing SourcesList is updated directly.

        This does not refresh our backing SourcesList.
        N)r\   r   rq   r<   rX   rZ   r   rN   )r0   rA   mergedentryr   r   r
   rr     s   	



zCollapsedSourcesList.refreshc                 C   s@  |j |j d}t|j}d}d}| jD ]}||r|}||r$|}|r*|r* nq|rB|r;t|j| }	t|	|_|j|ddS |r[|j|ddd}
|
|
j |   | |S |ru|| j	jv ru| j	j
|d }| j	j|| n|r|| j	jv r| j	j
|}| j	j|| n| j	j| | jt|| j	 |S )a_   Add a new entry to the sources.list.

        This will try to find an existing entry, or an existing entry with
        the opposite 'disabled' state, to reuse.

        If an existing entry does not exist, new_entry is inserted.
        If either 'after' or 'before' are specified, and match an existing
        SourceEntry in our list, then new_entry will be inserted before
        or after the specified SourceEntry.  If both 'after' and 'before'
        are provided, 'after' has precedence.  If neither 'after' or 'before'
        are provided, new_entry is appended to the end of the list.
        )r   NT)r`   )r`   ra   r[   )rD   r   r,   r"   r\   rX   re   ri   rr   r   r^   r_   r   rN   )r0   r   afterr   inverser"   match_entrymatch_inverserg   inverse_compsnew_inverse	new_indexr   r   r
   r     sB   





zCollapsedSourcesList.add_entryc                 C   s0   |  |}|rtt|jt|j |_dS dS )a)   Remove the specified entry form the sources.list

        This removes as much as possible of the entry.  If the entry
        matches an existing entry in our list, but our entry contains
        more components, only the specified components will be removed
        from our list's entry.  Similarly, if entry contains multiple
        components, this will remove those components from one or multiple
        entries, if needed.

        Any entries in our list that have all their components removed will
        be removed from our list.
        N)get_merged_entryr\   r,   r"   )r0   rA   rg   r   r   r
   remove_entry)  s   
z!CollapsedSourcesList.remove_entryc                 C   s   |  |}|r||jS dS )aR   If we already contain new_entry, find and return it

        If new_entry is already contained in our list, with at least
        all the components in new_entry, this returns our existing entry.
        The returned entry may have more components than new_entry.

        If new_entry is not contained in our list, or we do not
        have all the components in new_entry, this returns None.

        This may combine multiple existing SourceEntry lines into a
        single SourceEntry line so it contains all the requested
        components.

        This returns a SourceEntry.
        N)r   re   r"   r0   r   rg   r   r   r
   re   :  s   
zCollapsedSourcesList.get_entryc                 C   s"   | j D ]}||r|  S qdS )a   This is similar to get_entry(), but we return the MergedSourceEntry

        This returns the MergedSourceEntry in our list that matches
        the new_entry.

        Note that this IGNORES any comps in the new_entry, so the
        returned MergedSourceEntry may have more or less comps than
        the new_entry.

        If we contain no match for the new_entry, return None.

        This method will never combine SourceEntry lines like the
        get_entry method sometimes does.

        This returns a MergedSourceEntry.
        N)r\   rX   r   r   r   r
   r   O  s
   

z%CollapsedSourcesList.get_merged_entryc                 C   s&   |  |}|rt|jt|jkS dS )aW   Check if we already contain new_entry

        If new_entry contains multiple components, they may be located
        in multiple lines; this only checks that all requested components,
        for exactly the SourceEntry that equals new_entry (besides comps),
        are included in our list.

        This will not change our list.
        F)r   r,   r"   r   r   r   r
   r   e  s   

zCollapsedSourcesList.has_entry)NN)rG   rH   rI   rJ   rQ   r   r   r2   r   r   rr   r   r   re   r   r   r   r   r   r
   r     s    

?r   )r   r   r   r   
aptsourcesr   aptsources.distror   initr   rN   rp   objectr   r   r   r   r
   <module>   s     ]