
    eeRS                     ~    d Z ddlZddlmZ ddlZddlmZmZ ddlm	Z	  G d de	j                        Z G d	 d
      Zy)a  
Copyright (c) 2022, Ian Santopietro
All rights reserved.

This file is part of RepoLib.

RepoLib is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

RepoLib is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with RepoLib.  If not, see <https://www.gnu.org/licenses/>.
    N)Path   )SourceSourceError)utilc                   .     e Zd ZdZdddef fdZ xZS )SourceFileErrorz Exception from a source file.r   )coder
   c                2    t        |   |i | || _        y)zwException with a source file

        Arguments:
            :code int, optional, default=1: Exception error code.
    N)super__init__r
   )selfr
   argskwargs	__class__s       ./usr/lib/python3/dist-packages/repolib/file.pyr   zSourceFileError.__init__"   s     	$)&)	    )__name__
__module____qualname____doc__intr   __classcell__)r   s   @r   r	   r	      s    ()* 3  r   r	   c                   N   e Zd ZdZddeddfdZd Zd Zdeddfd	Z	d
eddfdZ
d
edefdZddZdededefdZddZddZedej&                  fd       Zej*                  dej&                  ddfd       Zedefd       Zedefd       Zedefd       Zedefd       Zy)
SourceFilea=   A Source File on disk
    
    Attributes:
        path(Pathlib.Path): the path for this file on disk
        name(str): The name for this source (filename less the extension)
        format(SourceFormat): The format used by this source file
        contents(list): A list containing all of this file's contents
    namereturnNc                 |   t        j                  t              | _        d| _        t               | _        t               | _        t        j                  j                  | _        g | _        g | _        |rJ|| _        | j                          | j                  j                         rg | _        | j!                          yyy)zInitialize a source file
        
        Arguments:
            name(str): The filename within the sources directory to load
         N)logging	getLoggerr   logr   r   pathalt_pathr   SourceFormatDEFAULTformatcontentssources
reset_pathexistsload)r   r   s     r   r   zSourceFile.__init__5   s     $$X.		!V(,(9(9(A(ADIOOyy! "		 "	 r   c                     | j                   S )N)outputr   s    r   __str__zSourceFile.__str__K   s    {{r   c                 "    d| j                    dS )NzSourceFile(name=))r   r/   s    r   __repr__zSourceFile.__repr__N   s    !$))A..r   sourcec                     || j                   vr>| j                  j                  |       | j                   j                  |       | |_        yy)zlAdds a source to the file
        
        Arguments:
            source(Source): The source to add
        N)r)   r(   appendfile)r   r4   s     r   
add_sourcezSourceFile.add_sourceQ   s@     %MM  (LL'FK &r   identc                 p   | j                  |      }| j                  j                  |       | j                  j                  |       | j	                          |j
                  }	 |j                         r|j                  r|j                          yyy# t        $ r Y yt        $ r t        j                         }	 |j                  dd      }|j                  t        |             Y y# t        j                   j"                  $ r* | j$                  j'                  d       t)        d       Y Y yw xY ww xY w)z}Removes a source from the file
        
        Arguments:
            ident(str): The ident of the source to remove
        org.pop_os.repolib/RepoDBus service not found!%Permission denied. Please use `sudo`.N)get_source_by_identr(   remover)   saveprefsr+   r   unlinkAttributeErrorPermissionErrordbus	SystemBus
get_objectdelete_prefs_filestr
exceptionsDBusExceptionr"   criticalprint)r   r9   r4   
prefs_pathbusprivileged_objects         r   remove_sourcezSourceFile.remove_source\   s     ))%0V$F#		 \\
	  "z!!# (7"  	 	.."C$'NN3G$Q!!33C
OD??00 !!";<=>	s1   %,B 	D5D5<,C**AD1-D50D11D5c                    | j                   j                  d| d| j                          | j                  D ]3  }|j                  |k(  s| j                   j                  | d       |c S  t        d| j                   d|       )zFind a source within this file by its ident
        
        Arguments:
            ident(str): The ident to search for
        
        Returns: Source
            The located source
        zLooking up ident z in z found	The file z does not contain the source )r"   debugr   r)   r9   r	   r#   )r   r9   r4   s      r   r?   zSourceFile.get_source_by_ident{   s     	*5'dii[ABll 	F||u$%/0	 		{"?wG
 	
r   c                    | j                   j                  d       t        j                  | j                   dz  }t        j                  | j                   dz  }|j                         r.|| _        || _        t        j                  j                  | _
        y|j                         r.|| _        || _        t        j                  j                  | _
        y|| _        || _        y)a  Attempt to detect the correct path for this File.
        
        We default to DEB822 .sources format files, but if that file doesn't
        exist, fallback to legacy .list format. If this also doesn't exist, we
        swap back to DEB822 format, as this is likely a new file.zResetting pathz.sourcesz.listN)r"   rU   r   SOURCES_DIRr   r+   r#   r$   r%   r&   r'   LEGACY)r   default_pathlegacy_paths      r   r*   zSourceFile.reset_path   s     	'(''TYYKx*@@&&DII;e)<< $DI'DM++33DK 	 !#DI(DM++22DK 	 %DI'DMr   source1source2c                 Z   |j                   }|j                   }| j                  j                  d| d| d       | j                  t        j
                  j                  k(  rt	        j                  ||       d}nLg d}t        |j                        dk(  rt        |j                        dk(  rt	        j                  |||      rit	        j                  ||       t        j                  j                  t        j                  j                  g|_	        d|_        |j                  |_        d}t	        j"                  |||      }|r|D ]z  }||   }|d   j%                         j'                         }	|d   j%                         j'                         }
|	D ]  }||
vs|d	| z  } n |
D ]  }||	vs|d	| z  } n ||k7  sz n |r||k7  r||_         ||_         y|rI||k(  rD| j(                  D ]4  }| j(                  j+                  |      }| j,                   d	| |_          y y|sy
y)az  Takes two sources with identical idents, and finds a new, unique
        idents for them.

        The rules for this are mildly complicated, and vary depending on the
        situation:

          * (DEB822) If the sources are identical other than some portion of 
            data, then the two will be combined into a single source.
          * (legacy) If the two sources are identical other than source type 
            (common with legacy-format PPAs with source code) then the second 
            source will be dropped until export.
          * (legacy) If the sources differ by URIs, Components, or Suites, then 
            the differing data will be appended to the sources' idents.
          * (Either) If no other rules can be determined, then the sources will 
            have a number appended to them
        
        Arguments:
            source1(Source): The original source with the ident
            source2(Source): The new colliding source with the ident
        
        Returns: bool
            `True` if the two sources were successfully deduped, `False` if the
            second source should be discarded.
        zIdents z and z	 conflictr   )X-Repolib-NamezX-Repolib-IDzX-Repolib-CommentEnabledTypesr   Tr   -F)r9   r"   rU   r'   r   r%   r&   combine_sourceslentypescompare_sources
SourceTypeBINARY
SOURCECODEtwin_sourceenabledsourcecode_enabledfind_differences_sourcesstripsplitr)   indexr   )r   r[   r\   
ident_src1
ident_src2	excl_keysdiffskey	raw_diffs
diff1_list
diff2_listir4   	src_indexs                 r   find_unique_identzSourceFile.find_unique_ident   s*   2 !
 
E*YGH;;$++333  '2JI 7==!Q&3w}}+=+B'')D((':..0J0J%GM +/G'18G.!#J11'7INE  C&+CjI!*1!3!3!5!;!;!=J!*1!3!3!5!;!;!=J' "J.&AaS'1J!" ( "J.&AaS'1J!" "Z/ *
2&GM&GMJ*4,,  LL..v6	"&))Ai[9  r   c                    | j                   j                  d| j                          g | _        g | _        | j
                  st        d      | j                  j                         st        d| j                   d      t        | j                  d      5 }|j                         }ddd       d}g }d}d	}d}i }D ]D  }	d	}
d
|	v }|s|	j                  d      }|rt        j                  |	j                               }|s-|s+| j                  j                  |	j                                n|r8| j                  t        j                   j"                  k7  r#t        d| j                  j
                   d      t%               }|j'                  |	g       |r||_        |j(                  s| j
                  |_        d}|j(                  |v rK||j(                     }|j+                  |j(                         | j-                  ||      }|||j(                  <   |||j(                  <   |r| |_        | j                  j                  |       | j                  j                  |       n|rdj1                  |	j3                  d      dd       }|j                         }n\|sYt        j                  |	j                               r5| j                  t        j                   j"                  k7  r#t        d| j                  j
                   d      t%               }|j'                  |	g       |r||_        |j(                  s| j
                  |_        d}|j(                  |v rK||j(                     }|j+                  |j(                         | j-                  ||      }|||j(                  <   |||j(                  <   |r=| |_        | j                  j                  |       | j                  j                  |       |	j                         d	k(  r| j                  j                  d	       t        j4                  D ]  }|	j                  |      s| j                  t        j                   j"                  k(  r#t        d| j                  j
                   d      d}|j                  |	j                                 |dz  }	|s|	j                         d	k(  rd}t%               }|j'                  |       | |_        |r||_        |j(                  s| j
                  |_        |j(                  |v rK||j(                     }|j+                  |j(                         | j-                  ||       |||j(                  <   |||j(                  <   | |_        | j                  j                  |       | j                  j                  |       g }|dz  }| j                  j                  d	       4|j                  |	       G |rd}t%               }|j'                  |       | |_        |r||_        |j(                  s| j
                  |_        |j(                  |v rK||j(                     }|j+                  |j(                         | j-                  ||       |||j(                  <   |||j(                  <   | |_        | j                  j                  |       | j                  j                  |       g }|dz  }| j                  j                  d	       | j                  D ]1  }|j6                  rt        d| j                  j
                   d       | j                   j                  d| j                         y# 1 sw Y   xY w)z'Loads the sources from the file on diskzLoading source file z$You must provide a filename to load.rT   z does not exist.rNr   Fr   r^   #zFile zk is an updated file, but contains legacy-format sources. This is not allowed. Please fix the file manually.T:r   zi is a DEB822-format file, but contains legacy sources. This is not allowed. Please fix the file manually.zE is malformed and contains errors. Maybe it has some extra new-lines?zFile %s loaded)r"   rU   r#   r(   r)   r   r	   r+   open	readlines
startswithr   validate_deblinerm   r6   r'   r%   rX   r   load_from_datar9   poprz   r7   joinrn   
valid_keyshas_required_parts)r   source_filesrcfile_dataitemraw822parsing_deb822source_name	commentedidentslinecomment_found	name_linevalid_legacy
new_sourceto_add
old_sourcert   r4   s                     r   r,   zSourceFile.load   s   -dii[9:yy!"HIIyy!!Idii[8H"IJJ$))S! 	3[&002L	3 #	 ! r	(D "M-5I! OOC0	 #'#8#8#FL'	,,TZZ\:%;;$*;*;*B*BB"1"'		'7 8I !I# 
 &,X
"114&9&.9JO)///3yyJ,&*%++v5)/
0@0@)AJ"JJz'7'78%)%;%;J
%SF7AF:#3#343=z//0!.2JO MM00< LL//
;"&)hhtzz#qr/B&C&1&7&7&9 #,,TZZ\:;;$*;*;*B*BB"1"'		'7 8I !I# 
 &,X
"114&9&.9JO)///3yyJ,&*%++v5)/
0@0@)AJ"JJz'7'78%)%;%;J
%SF7AF:#3#343=z//0!.2JO MM00< LL//
; ::<2%MM((,  ?? 	4Cs+;;$*;*;*B*BB"1"'		'7 8@ !@# 
 *.djjl3	4 	::<2%%*N!'J--f5&*JO"*5
%++/3yyJ,!''61%+J,<,<%=


:#3#34..z:F3=z//0/9F:++,&*JOMM((4LL''
3FAIDMM((,MM$'er	(h "NJ%%f-"JO"-
###'99
 6)#J$4$45


:++,&&z:>+5z''('1F:##$"JOMM  ,LL
+FAIDMM  $ll 	F,,%		/ 0A A 	 	'3y	3 	3s   ^^c                    | j                   j                  d| j                          | j                  D ])  }| j                   j                  d|j                  |       + t
        j                  | j                   dz  }| j                  D ]8  }|j                  r|j                  j                          |j                          : | j                  r| j                  st        d      t
        j                  j                         s!	 t
        j                  j                  d       t#        | j                        dkD  r| j                   j                  d	| j                  | j$                         	 t'        | j                  d
      5 }|j)                  | j*                         ddd       | j$                  j                         r| j$                  j-                  |       | j                   j                  d| j                         y	 | j                  j?                  d       | j$                  j?                  d       |j?                  d       | j                   j                  d| j                         y# t        $ r | j                   j!                  d       Y zw xY w# 1 sw Y   xY w# t        $ r t/        j0                         }	 |j3                  dd      }|j5                  | j                  j                  | j*                         nJ# t.        j6                  j8                  $ r* | j                   j;                  d       t=        d       Y Y yw xY wY w xY w# t        $ r t/        j0                         }	 |j3                  dd      }|jA                  | j                  j                         nJ# t.        j6                  j8                  $ r* | j                   j;                  d       t=        d       Y Y yw xY wY w xY w)z6Saves the source file to disk using the current formatzSaving source file to zNew Source %s: 
%sz.savez)There was not a complete filename to saveT)parentszSSource destination path does not exist and cannot be created Failures expected now.r   z"Saving, Main path %s; Alt path: %sw)modeNr;   r<   r=   r>   zFile %s saved)
missing_okzFile %s removed)!r"   rU   r#   r)   r9   r   rW   r   rt   save_gpg
tasks_saver'   r	   r+   mkdirrE   errorrc   r$   r   writer.   renamerF   rG   rH   output_file_to_diskrK   rL   rM   rN   rC   delete_source_file)r   r4   	save_pathoutput_filerP   rQ   s         r   rA   zSourceFile.save  s"   /		{;<ll 	HFHHNN0&,,G	H $$$))E'::	ll 	 Fzz

##%	 
 yy!"MNN&&(  &&t&4 t||q HHNN?DMMZ$))#. 3+%%dkk23=='')MM((3 HHNN?DII6		  D 1$$$5  D 1 HHNN,dii8M # -3 3
 # nn&(+7KW(U%%99$))..$++V44 HH%%&?@AB W	 # nn&(+7KW(U%%88H44 HH%%&?@AB I	s   
 I= 4J5 J('=J5 A
M' =$J%$J%(J2-J5 5M$ALM$AMM$MM$#M$'P7N=<P=AP PPP
Pc                     | j                   S )zThe format of the file on disk)_formatr/   s    r   r'   zSourceFile.format  s     ||r   r'   c                 X   t         j                  j                  }|| _        t         j                  | j
                   d| j                  j                   z  | _        t         j                  D ]
  }||k7  s	|} t         j                  | j
                   d|j                   z  | _        y)z4The path needs to be updated when the format changes.N)	r   r%   rX   r   rW   r   valuer#   r$   )r   r'   
alt_formatformat_s       r   r'   zSourceFile.format  s     (,'8'8'?'?
$$$))Adll6H6H5I'JJ	(( 	%G $
	% ((dii[*:J:J9K+LLr   c                 ~    d}| j                   D ]  }	 ||j                  z  }|dz  } |S # t        $ r ||z  }Y w xY w)z,Outputs the file in the output_legacy formatr   
)r(   legacyrD   )r   legacy_outputr   s      r   r   zSourceFile.legacy  s^     MM 	"D&, T!M	"  " &%&s   +<<c                 ~    d}| j                   D ]  }	 ||j                  z  } |S # t        $ r ||z  }|dz  }Y ,w xY w)z)Outputs the file in the output_822 formatr   r   )r(   deb822rD   )r   deb822_outputr   s      r   r   zSourceFile.deb822  s\     MM 	&D&,	&  " &%%&s   &<<c                 t    d}| j                   D ]  }	 ||j                  z  }|dz  } |S # t        $ r Y w xY w)z(Outputs the file in the output_ui formatr   r   )r(   uirD   )r   	ui_outputr   s      r   r   zSourceFile.ui  sW     	MM 	DTWW$	 I	  " s   +	77c                 D   d}| j                   D ]u  }	 | j                  t        j                  j                  k(  r||j
                  z  }n;| j                  t        j                  j                  k(  r||j                  z  }|dz  }w |S # t        $ r ||z  }|dz  }Y w xY w)z%Outputs the file in the output formatr   r   )	r(   r'   r   r%   r&   r   rX   r   rD   )r   default_outputr   s      r   r.   zSourceFile.output  s      MM 		'D';;$"3"3";";;"dkk1N[[D$5$5$<$<<"dkk1N"d*N		'  " '$&$&'s   A2B		BB)r   )r   N)r   r   r   r   rJ   r   r0   r3   r   r8   rR   r?   r*   boolrz   r,   rA   propertyr   r%   r'   setterr   r   r   r.    r   r   r   r   +   sK   C t ,/	 	4 	# $ >
 
 
$6Q Q Q4 Qhh4T:9| ))   ]]MD-- M$ M M 	 	 	 	 	 	 	C 	 	   r   r   )r   r    pathlibr   rF   r4   r   r   r   r   	RepoErrorr	   r   r   r   r   <module>r      s7   &    ' 
dnn 
~ ~r   