S9y@sFddlmZddlZddlmZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlmZmZde jkrejjddejjddnGd d d eZGd d d eZdS) )print_functionN)FetchFailedException)BytesIOopenZAPT_CLONE_DEBUG_RESOLVERzDebug::pkgProblemResolver1zDebug::pkgDepCache::AutoInstallc@sgeZdZdZdZddZddZddd Zd d Zd d Z ddZ dS)LowLevelCommandszN calls to the lowlevel operations to install debs or repack a deb z/usr/bin/dpkg-repackcCsb|s dSddg}|dkrE|jdd|jd|ntj||}|dkS)NTZdpkgz-i/rchroot)insert subprocesscall)selfZdebfiles targetdirZ install_cmdretr7/usr/lib/python3/dist-packages/DistUpgrade/apt_clone.py install_debs1s  zLowLevelCommands.install_debscCstjj|js+td|jn|jg}tjdksrtjjds_dSddg|}ntj||gd|}|dkS)z$ dpkg-repack pkgname into targetdir z no '%s' foundrz/usr/bin/fakerootNZfakerootz-ucwd)ospathexists dpkg_repackIOErrorgetuidr r )rpkgnamerZ repack_cmdrrrr repack_deb;s zLowLevelCommands.repack_debNcCsM|dkr+ddl}|jd}ntjd||g}|dkS)NrZCODENAME debootstrap) lsb_releaseZget_distro_informationr r )rrdistrorrrrrrGs   zLowLevelCommands.debootstrapcCs(tjdd|d|g}|dkS)Nzapt-keyz --keyringaddr)r r )rZ fromkeyfileZ intokeyfilerrrr merge_keysNszLowLevelCommands.merge_keyscCs%tjdd||g}|dkS)NZmountz--bindr)r r )rZolddirZnewdirrrrr bind_mountSszLowLevelCommands.bind_mountcCstjd|g}|dkS)NZumountr)r r )rZbinddirrrrr bind_umountWszLowLevelCommands.bind_umount) __name__ __module__ __qualname____doc__rrrrr!r"r#rrrrr+s    rc@seZdZdZdejdZdZdddddZdddd d Z d d Z d dZ ddZ ddZ ddZddZddZdddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,d-Zd+ddd.d/Zdd0d1Zd2d3Zd4d5Zdd6d7Zd8d9Z d:d;Z!d<d=Z"d>d?d@Z#d+dAdBZ$dCdDZ%dS)EAptClonez clone the package selection/installation of a existing system using the information that apt provides If dpkg-repack is installed, it will be used to generate debs for the obsolete ones. zapt-clone-state-%s.tar.gzr z./NcCst|_t|_t|_|r6||_ntjjj |_|r]||_ ntjj j |_ |r||_ n tj|_ dS)N)setnot_downloadableversion_mismatchrcommandsfetch_progressaptprogresstextAcquireProgressinstall_progressbaseZInstallProgress _cache_clsZCache)rr-r2Z cache_clsrrr__init__gs      zAptClone.__init__Fc CsFtjj|r-tjj||j}n|jdsI|d7}n|dkrtjtjj d|tjj dtjj|dtj nt j d|dd }|j ||j|||j||j|||j||j||r&|j|n|r<|j|nWd QXd S) z save the current system state (installed pacakges, enabled repositories ...) into the apt-state.tar.gz file in targetdir z.tar.gzz.apt-clone.tar.gzrZDirzDir::State::statuszvar/lib/dpkg/statusnamemodezw:gzN)rrisdirjoinCLONE_FILENAMEendswithapt_pkgZ init_configconfigr)Z init_systemtarfiler _write_uname_write_state_installed_pkgs_write_state_auto_installed_write_state_sources_list_write_state_apt_preferences_write_state_apt_keyring_write_state_dpkg_status _dpkg_repack)r sourcedirtargetZwith_dpkg_repackZwith_dpkg_statusZ scrub_sourcestarrrr save_states*         zAptClone.save_statecCsPitjdd6tjdd6tjdd6tjjdd6}|S) Nr hostnameZkernelZ uname_archzAPT::Architecturearch)runamer<r=find)r host_inforrr_get_host_info_dicts zAptClone._get_host_info_dictcCsu|j}tjdd}djdd|jD}|j|d|j|j|jdddS)Nr7w cSs&g|]\}}d||fqS)z%s: %sr).0keyvaluerrr s z)AptClone._write_uname..arcnamez./var/lib/apt-clone/uname) rRtempfileNamedTemporaryFiler9itemswriteflushr r6)rrIrQfinforrrr?s  zAptClone._write_unamecCs|jd|}d}x|D]}|jr|d|j|jjt|jf7}|j sn|jj r|j j |jq|jjo|jjs|j j |jqqqWt j d}|jd}t||_tj|_|j|t|dS)Nrootdirz %s %s %s z"./var/lib/apt-clone/installed.pkgszutf-8)r4 is_installedr6 installedversionintis_auto_installed candidateZ downloadabler*r r+r>ZTarInfoencodelensizetimemtimeZaddfiler)rrGrIcachespkgtarinforrrr@s   #  z$AptClone._write_state_installed_pkgscCs)tjjd}|j|dddS)Nzdir::state::statusrYz./var/lib/apt-clone/dpkg-status)r<r= find_filer )rrI dpkg_statusrrrrEsz!AptClone._write_state_dpkg_statuscCs;tjjd}tjj|r7|j|dndS)NzDir::State::extended_statesz#./var/lib/apt-clone/extended_states)r<r=rrrrrr )rrIZextended_statesrrrrAs  z$AptClone._write_state_auto_installedcCs{tjjd}tjj|r:|j|ddntjjdd}tjj|rw|j|ddndS)NzDir::Etc::preferencesrYz./etc/apt/preferenceszDir::Etc::preferencespartsz/etc/apt/preferences.dz./etc/apt/preferences.d)r<r=rrrrrr find_dir)rrIr_prrrrCs  z%AptClone._write_state_apt_preferencescCs{tjjd}tjj|r:|j|ddntjjdd}tjj|rw|j|ddndS)NzDir::Etc::trustedrYz./etc/apt/trusted.gpgzDir::Etc::trustedpartsz/etc/apt/trusted.gpg.dz./etc/apt/trusted.gpg.d)r<r=rrrrrr rt)rrIr_rurrrrDs  z!AptClone._write_state_apt_keyringcCstjjd}|j|||dtjjd}tjj|r|j|ddddxtj |D]r}|j drqun|j d sqund ||f}tjj |rqun|j|||d |quWndS) NzDir::Etc::sourcelistz./etc/apt/sources.listzDir::Etc::sourcepartsrYz./etc/apt/sources.list.dZ recursiveF.z.listz%s/%sz./etc/apt/sources.list.d/) r<r=rr$_add_file_to_tar_with_password_checkrtrrrr listdir startswithr;r8)rrIscrubZ sources_listZ source_partssourceZsources_file_namerrrrBs$ z"AptClone._write_state_sources_listcCs|rtjdd}t|d}x|jD]t}t|tkrd|jd}ntjd|rtj dd|}n|j |j d|j q:W|j |jd|WdQXWdQXn|j |d|dS) Nr7wbrbzUTF-8z/[^/@:]*:[^/@:]*@z/USERNAME:PASSWORD@zutf-8rY)rZr[r readlinestypebytesdecoderesearchsubr]rir^r r6)rrIsourcesrzrYZ source_copyr_linerrrrws' %z-AptClone._add_file_to_tar_with_password_checkcCsdS)Nr)rrIrrr_write_modified_files_from_etcsz'AptClone._write_modified_files_from_etccCsWtj}x$|jD]}|jj||qW|j|ddtj|dS)NrYz./var/lib/apt-clone/debs)rZmkdtempr*r,rr shutilrmtree)rrIZtdirrrrrrFs  zAptClone._dpkg_repackcCs2|jdjdr%d|_n d|_dS)Nr z./rb)getnamesry TARPREFIX)rrIrrr_detect_tarprefixs zAptClone._detect_tarprefixc Cstj|}|j||j|jd}x|jD]v}|jd}|jdsB|jdkr~qBn|j }t |dkrB|dj d rB|dSqBWWdQXdS)Nzetc/apt/sources.listzutf-8#rbrLr) r>rr extractfilerr~rrystripsplitrjr;)r statefilerIr_rlrrr_get_info_distro#s ! &zAptClone._get_info_distroc Cs|j|pd}tj|}|j|jd}d}}g}x|jD]r}|jd}|jj\} } } |d7}t | r|d7}n| j drZ|j | qZqZW|j |jd} | j } d}d}|jd|jkrf|j|jdj}tj|}|jdd}|jd d}ni|d6|d 6d j|d 6|d 6|d6tj| d6|d 6SWdQXdS)Nunknownz var/lib/apt-clone/installed.pkgsrzutf-8r z-desktopzvar/lib/apt-clone/unamerKrNrz, metard autoinstalleddate)rr>rrrr~rrrrfr;appendZ getmemberrmrreadr<Z TagSectiongetr9rlZctime)rrrrIr_rdrrrr6reautomrrKrNr`Zsectionrrr_get_clone_info_dict1s@      zAptClone._get_clone_info_dictcCsd|j|S)NzHostname: %(hostname)s Arch: %(arch)s Distro: %(distro)s Meta: %(meta)s Installed: %(installed)s pkgs (%(autoinstalled)s automatic) Date: %(date)s )r)rrrrrr`Ysz AptClone.infoc Cstj|g}|j||j|j|dd}g}x*|jD]}|j|jdqRWWdQX||}tj j |rt|}|j} WdQXng} t j | |dd|d|} g} x| D]}| j|qW| S)Nr zutf-8Zfromfilezcurrent-system%sZtofile) r>rrrrr~rrrrrdifflibZ unified_diff) rrZ system_filerrIZ clone_fileZclone_file_linesrfpZsystem_file_linesgendiffrrr_get_file_diff_against_clonebs$      z%AptClone._get_file_diff_against_clonerc Csh|dkr"tjjd|ntd|j}|j|}xd|D]\}|j|d|j|dkrNtd||j|d|j|dfqNqNWtdd}|j|||}|rtdj|n|j d|}t j |} | j |j d} i} xo| jD]a} | jjd } | jd s<| dkrxq<n| j\} }}||f| | z %s <%s> <%s>)r<r=r)printrRrrrr9r4r>rrrr~rrryrrdrestrrgr6keyssortedr )rrrrQZ clone_inforVZsources_list_systemrrnrIr_Zinstalled_in_clonerr6rerZinstalled_on_systemrpZonly_on_systemZ only_in_cloneZpkgversion_differencesrZclone_file_pkgversionZ clone_is_autoZsystem_pkgversionZ sys_is_autoZ clone_verZ system_verrrr show_diffysp    $   &"  "       zAptClone.show_diffc Cs}|dkrftjjd||jjdtjj|d|jjdtjj|dntj |}|j |WdQXtjj |st d||j |}|jj||n|j|||j|||r |j||n|j||||j|||dkry|jjtjj|d|jjtjj|dndS) z take a statefile produced via (like apt-state.tar.gz) save_state() and restore the packages/repositories into targetdir (that is usually "/") rzDPkg::Chroot-Directoryz/procprocz/syssysNz0Dir '%s' does not exist, need to bootstrap first)r<r=r)r,r"rrr9r>rrrrrr_restore_sources_list_restore_apt_keyring_rewrite_sources_list_restore_package_selection_restore_not_downloadable_debsr#)rrr new_distroprotect_installedrIrrrr restore_states& "% zAptClone.restore_statec Cstj}tjjd}tjj|tjj|s`tj |tjj|nt j ||||j |||r|j ||n|jd|}y|jtjjjWntk rYnX|j|j||}t j||S)Nzdir::state::statusra)rZrr<r=rrrrrdirnamemakedirsrcopyrrr4updater.r/r3r1rr#_restore_package_selection_in_cacher)rrrrHrsrnmissingrrrsimulate_restore_states" "    zAptClone.simulate_restore_statecCstj|}tjj|ddd}tjj|rVtj|d|n|j|j d|tjj|ddd}tj |t j t j Bt jBt jBy|j|j d|Wntk rYnXWdQXdS)Netcr.z sources.listz %s.apt-clonezetc/apt/sources.listzetc/apt/sources.list.d)r>rrrr9rrrextractrchmodstatS_IRUSRS_IWUSRS_IRGRPS_IROTHKeyError)rrrrIexistingZ td_sourcesrrrrs  zAptClone._restore_sources_listcCstjj|ddd}d|}tjj|rJtj||ntj|}y|j|j d|Wnt k rYnXy|j|j d|Wnt k rYnXtjj|r|j j ||tj |nWdQXdS)Nrr.z trusted.gpgz %s.apt-clonezetc/apt/trusted.gpgzetc/apt/trusted.gpg.d)rrr9rrrr>rrrrr,r!remove)rrrrZbackuprIrrrrs    zAptClone._restore_apt_keyringcCszt}t}tj|j}|rZx-|D]"}|jr1|j|jq1q1Wntj|}|j |j d} |j jxb| j D]T} | j jd} | jds| dkrqn| j\} } } |j| t| }| }| |kryw|r{|| jd|dd|jdkr|j|| jsxtd | qxqn|| jd|WnItk r}z)tjd | |f|j| WYdd}~XnX|| j|qqWWdQXWdQX|jdkr|jnxW|D]O}||krH|j|q#n||jp_||js#|j|q#q#W|S) Nz var/lib/apt-clone/installed.pkgszutf-8rrb from_userZauto_fixFrzpkg %s not marked upgradezcan't add %s (%s))r)r<ZProblemResolverZ _depcachercZprotectZ_pkgr>rrrZ actiongroupr~rrryrr rfZ mark_installZ broken_countZresolveZmarked_install SystemErrorloggingZwarningZ mark_auto)rrrnrrZpkgsZresolverrprIr_rr6rerZauto_installedrerrrr sR           $    z,AptClone._restore_package_selection_in_cachec Cs|jd|}tjjjddtjjjddy|j|jWntk rfYnX|j|j ||||j |j|j dS)NrazDir::BinrzDir::Bin::dpkgz /usr/bin/dpkg) r4r.r<r=r)rr-rrrZcommitr2)rrrrrnrrrrUs  z#AptClone._restore_package_selectionc stj|S}y3fdd|jD}|j||Wntk r]dSYnXWdQXg}tjj|d}xHtjtjj|dD](}tjj||}|j |qWj j ||dS)Ncs/g|]%}|jjjdr|qS)zvar/lib/apt-clone/debs/)r6ryr)rUrq)rrrrXis z;AptClone._restore_not_downloadable_debs..z./var/lib/apt-clone/debsz*.deb) r>rZ getmembersZ extractallrrrr9globrr,r) rrrrIZdebsdirZdebsrZdebZdebpathr)rrrfs %z'AptClone._restore_not_downloadable_debsc Cs4ddlm}m}tjjdtjjtjj |dddtjjdtjjtjj |ddd|}x|j ddD]z}|j s|j rqnd }x8dD]0}|j jd |rd||f}PqqW|r ||_ q||_ qWtjj |ddd} tjjd} tjj| rt| dX} xN| D]F} || | } | j s| j s| |krq|j j| qqqqWWdQXtj| nxR|j D]G}|jjdr|j j||j jd|d|_ qqW|jdS)Nr) SourcesList SourceEntryzDir::Etc::sourcelistrr.z sources.listzDir::Etc::sourcepartszsources.list.drbupdatessecurity backportsz-%sz%s-%szsources.list.apt-clonerzcdrom:T)rrr)Zaptsources.sourceslistrrr<r=r)rrabspathr9listZinvalidZdisabledZdistr;rrrrrrZuriryr Zsave)rrrrrrentryZ replacementZpocketrZ sourcelistrrsrcrrrrtsF ( (      zAptClone._rewrite_sources_listrbc CsJ|rtjj|d}nd}t}tjjtjjd}xztjtjj|ddD]W}t |dd=}x3|D]+}|j dr|j |j qqWWdQXqmWt}xrtj |D]a\} } } xO| D]G} tjj| t|d| } | |kr|j | qqWqW|S) Nrz/etczDir::State::statusr`z*.listencodingzutf-8z/etc/)rrr9r)rr<r=rrrryr rwalkrj)rrGZetcdirZownedZ dpkg_basedirr_rrZunowneddirpathZdirnames filenamesr6fullnamerrr_find_unowned_in_etcs" ( $  % zAptClone._find_unowned_in_etcc Cs|tjjd}t}t|s}tj|}xZ|D]R}d|krDx=|djdD]%}d}t|jdkr|j\} } }n|j\} } || } | j} |dkrqjnt j j | st j d| |j| qjntj} t| d}| j|jWdQX| j| krjt j d| | j| f|j| qjqjWqDqDWWdQX|S) NzDir::State::statusZ conffilesrTobsoletezconffile %s removedr}zconffile %s (%s != %s))r<r=rPr)rZTagFilerrjrrrrrdebugr hashlibmd5rrZ hexdigest) rrGrsZmodifiedrtagrrrr6Zmd5sumrrrrr_find_modified_conffiless6         !z!AptClone._find_modified_conffilescCstddS)Nznot implemented yet)r)rrGrrr_dump_debconf_databaseszAptClone._dump_debconf_database)&r$r%r&r'rrOr:rr5rJrRr?r@rErArCrDrBrwrrFrrrr`rrrrrrrrrrrrrrrrrr(\sF          ( K#  5   *#r()Z __future__rr.Z apt.cacherr<rrrrrrrrr r>rZrliorrenvironr=r)objectrr(rrrrs*              1