o
    +ke                    @   s  d dl Z d dlZzMd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlmZmZ d dlmZ d dlmZmZ d dlmZ ddlmZm Z  e Zd dl!Z!ddl"m#Z# dd	l"m$Z$ dd
l%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z, ddl'm-Z-m.Z.m/Z/m0Z0m1Z1 ddl'm2Z2m3Z3m4Z4m5Z5 ddl'm6Z6 ddl7m8Z8m9Z9m:Z: ddl;T ddl<m=Z= ddl>m?Z?m@Z@mAZAmBZBmCZCmDZD ddlEmFZF ddl$mGZGmHZHmIZImJZJ ddl$mKZKmLZLmMZM ddl$mNZNmOZOmPZPmQZQmRZR ddl$mSZSmTZTmUZUmVZVmWZW ddl$mXZXmYZYmZZZ ddl$m[Z[m\Z\m]Z]m^Z^ ddl$m_Z_m`Z`maZambZbmcZc ddl$mdZdmeZemfZfmgZg ddl$mhZhmiZi ddl$mjZjmkZk ddl$mlZlmmZm ddl$mnZn dd l$moZo dd!l$mpZpmqZq dd"l$mrZrmsZsmtZtmuZumvZv dd#l$mwZw dd$l$mxZxmyZymzZzm{Z{ dd%l$m|Z| dd&l$m}Z} dd'l$m~Z~mZ dd(l$mZ dd)l$mZmZ dd*l$mZmZmZ dd+l$mZ dd,l$mZ dd-l$mZmZmZ dd.l$mZ dd/l$mZmZ dd0l$mZ dd1l$mZ dd2lmZmZ dd3lmZ dd4lmZmZmZmZ dd5lmZ dd6lmZmZ dd7lmZmZmZ dd8lmZmZ dd9lmZmZmZ dd:lmZmZmZmZmZ dd;lmZ dd<lmZmZ W n eyi   e  e d= Y nw eId=kssJ d>d?Zd@ZeedAreejej_dBdC Z	E	E	dYdFdGZdHdI ZdJdK ZdLdM ZG dNdO dOejZG dPdQ dQZdRdS ZdTdU ZdVdW ZedXkreƃ  dS dS )Z    N)	unhexlifyhexlify)contextmanager)datetime	timedelta)TextIOWrapper   )create_loggersetup_logging)__version__)helpers)crc32)ArchiveArchiveCheckerArchiveRecreater
Statistics
is_special)BackupErrorBackupOSError	backup_ioOsOpenstat_update_check)FilesystemObjectProcessorsTarfileObjectProcessorsMetadataCollectorChunksProcessor)has_link)Cacheassert_secureSecurityManager)*)CompressionSpec)key_creatorkey_argument_namestam_required_filetam_requiredRepoKeyPassphraseKey)
KeyManager)EXIT_SUCCESSEXIT_WARNING
EXIT_ERROREXIT_SIGNAL_BASE)ErrorNoManifestErrorset_ec)positive_int_validatorlocation_validatorarchivename_validatorChunkerParamsLocation)
PrefixSpecGlobSpecCommentSpec
SortBySpecFilesCacheMode)BaseFormatterItemFormatterArchiveFormatter)format_timedeltaformat_file_sizeparse_file_sizeformat_archive)safe_encoderemove_surrogates
bin_to_hexprepare_dump_dicteval_escapes)intervalprune_withinprune_splitPRUNING_PATTERNS)	timestamputcnow)get_cache_diros_stat)ManifestAI_HUMAN_SORT_KEYS)hardlinkable)
StableDict)check_pythoncheck_extension_modules)dir_is_taggedis_slow_msgpackis_supported_msgpackyessysinfo)	log_multi)signal_handlerraising_signal_handlerSigHupSigTerm)ErrorIgnoringTextIOWrapper)ProgressIndicatorPercent)basic_json_data
json_print)replace_placeholders)ChunkIteratorFileWrappernormalize_chunker_params)popen_with_error_handlingprepare_subprocess_envcreate_filter_process)	dash_open)umount)	flags_dirflags_special_followflags_special)msgpack)sig_intignore_sigint)iter_separated)get_tar_filter)BorgJsonEncodersafe_decode)rst_to_terminal)ArgparsePatternActionArgparseExcludeFileActionArgparsePatternFileActionparse_exclude_pattern)PatternMatcher)ItemArchiveItem)	get_flagsget_process_idSyncFile)uid2user	gid2group)RepositoryServerRemoteRepositorycache_if_remote)
RepositoryLIST_SCAN_LIMITTAG_PUT
TAG_DELETE
TAG_COMMIT)selftest)AtticRepositoryUpgraderBorgRepositoryUpgrader   zZEXIT_ERROR is not 2, as expected - fix assert AND exception handler right above this line.zN                       Original size      Compressed size    Deduplicated sizezCUsing a pure-python msgpack! This will result in lower performance.fully_trusted_filterc                    s<   t |tr
t |S t |ttfrt fdd|D S |S )zSIf bool is passed, return it. If str is passed, retrieve named attribute from args.c                 3   s    | ]}t  |V  qd S N)getattr.0itemargs 1usr/lib/python3.10/site-packages/borg/archiver.py	<genexpr>s       zargument.<locals>.<genexpr>)
isinstancestrr   listtupleany)r   Zstr_or_boolr   r   r   argumentn   s
   

r   FTc	           
   	      sx   ssrdu rt dtturt dndur%t dt r*tj|  f	dd}	|	S )u  
    Method decorator for subcommand-handling methods: do_XYZ(self, args, repository, …)

    If a parameter (where allowed) is a str the attribute named of args is used instead.
    :param fake: (str or bool) use None instead of repository, don't do anything else
    :param create: create repository
    :param lock: lock repository
    :param exclusive: (str or bool) lock repository exclusively (for writing)
    :param manifest: load manifest and key, pass them as keyword arguments
    :param cache: open cache, pass it as keyword argument (implies manifest)
    :param secure: do assert_secure after loading manifest
    :param compatibility: mandatory if not create and (manifest or cache), specifies mandatory feature categories to check
    Nz=with_repository decorator used without compatibility argumentzFwith_repository decorator compatibility argument must be of type tuplezFwith_repository called with compatibility argument but would not checkc                    s,   t   	f
dd}|S )Nc           
         s  t |d }|j}t |dd}t |dd }t |dd}t|A r-| |fdd i|S |jdkrEt| t|| j||||d}nt|jt|| j||||d	}| s]rt	
|\|d
< |d< d|v rt|jj|d _	rt||d
 | j rt||d |d
 t |dd| jt |dtt |ddt |ddd}	| |f||	d|W  d    W  d    S 1 sw   Y  n| |fd|i|W  d    S W d    d S 1 sw   Y  d S )Nlockappend_onlyFstorage_quotamake_parent_dirs
repositoryZssh)create	exclusive	lock_waitr   r   r   r   )r   r   r   r   r   r   r   manifestkeycompressionprogressfiles_cache_modeconsider_part_filesiec)r   r   
cache_moder   r   )r   cache)r   locationr   protor   Zomit_archiver   r   pathrN   loadr   Z
compressorr   r   ZFILES_CACHE_MODE_DISABLED)
selfr   kwargsr   r   r   r   r   r   Zcache_)
_lockr   compatibilityr   r   fakeinvert_faker   methodsecurer   r   wrapper   sN   



"z3with_repository.<locals>.decorator.<locals>.wrapper	functoolswrapsr   r   	r   r   r   r   r   r   r   r   r   r   r   	decorator   s     z"with_repository.<locals>.decorator)AssertionErrortyper   reprrN   NO_OPERATION_CHECK)
r   r   r   r   r   r   r   r   r   r   r   r   r   with_repositoryw   s   	#r   c                    s   t   fdd}|S )Nc                    sx   t ||||jjt|ddt|ddpt|ddt|ddt|dd|d|j|j|jd} | |f||||d	|S )
Nnumeric_idsF
nobsdflagsnoflagsnoaclsnoxattrsr   )r   r   r   r   r   r   log_jsonr   )r   r   r   archive)r   r   r   r   getr   r   r   )r   r   r   r   r   r   r   r   r   r   r      s   


zwith_archive.<locals>.wrapperr   r   r   r   r   with_archive   s   	r   c                 C   s&   t | }|t dk rtd|  |S )N10Mz3quota is too small (%s). At least 10M are required.)r?   argparseArgumentTypeError)r   parsedr   r   r   parse_storage_quota   s   r   c                 C   s.   dD ]}t | |d }|d ur|  S qtd)N)funcfallback_funcfallback2_funcz"expected func attributes not found)r   	Exception)r   namer   r   r   r   get_func   s   r   c                   @   s   e Zd ZdZdddZdS )
Highlanderz(make sure some option is only given onceNc                 C   s2   t || jd | jkrt| dt|| j| d S )NzThere can be only one.)r   destdefaultr   ZArgumentErrorsetattr)r   parser	namespacevaluesZoption_stringr   r   r   __call__   s   zHighlander.__call__r   )__name__
__module____qualname____doc__r   r   r   r   r   r      s    r   c                   @   sp  e Zd ZdddZdd Zdd Zdd	 Zed
d Zdd Z	e
dddddd Ze
ddddd Ze
ejjfddd Ze
ddddddd Ze
ddddddd Ze
dddd  Zd!d" Ze
d#dejjfd$dd%d&Zd'd( Zd)d* Zed+d, Ze
ejjfded-d. Ze
ejjfded/d0 Zd1d2 Ze
ejjfded3d4 Ze
ddejjfd5ed6d7 Z d8d9 Z!e
dddd:d; Z"d<d= Z#d>d? Z$d@dA Z%e
ejjfddBdC Z&dDdE Z'e
ejjfddFdG Z(dHdI Z)dJdK Z*e
dejjfdLdMdN Z+dOdP Z,dQdR Z-e
dejj.fdSdTdU Z/e
dVddddWddXdYZ0e
ddejjfdZd[d\ Z1e
ddejjfdZd]d^ Z2d_d` Z3e
dddadbdc Z4e
dddaddde Z5e
ddddfdg Z6dhdi Z7e
ej8ddjdk Z9e
ej8ddldm Z:e
ej8ddndo Z;e
dddpdq Z<e
dddrds Z=e
dddtdu Z>e
ej8ddvdw Z?e
dddadxdy Z@e
dddadzd{ ZAe
dddej8d|d}d~ ZBe
dddadd ZCdd ZDe
ddddd ZEeFG ZHeIJdeHd< eIJdeHd< eIJdeHd< dd ZKdd ZLeLZMdd ZNG dd dZOdd ZPdd ZQdddZRdd ZSdd ZTdd ZUdd ZVdS )ArchiverNc                 C   s    t | _|| _|| _t | _d S r   )r)   	exit_coder   progtime	monotoniclast_checkpoint)r   r   r   r   r   r   __init__   s   zArchiver.__init__c                 G   $   |r|| p|}t | _t| d S r   )r+   r   loggererrorr   msgr   r   r   r   print_error      zArchiver.print_errorc                 G   r   r   )r*   r   r   warningr   r   r   r   print_warning   r   zArchiver.print_warningc                 C   st   | j r4|d ur6| jd u s|| jv r8| jr&ttd|t|dtjd d S t	
dd|t| d S d S d S d S )NZfile_status)r   statusr   fileborg.output.listz%1s %s)output_listoutput_filterr   printjsondumpsrB   sysstderrlogging	getLoggerinfo)r   r   r   r   r   r   print_file_status   s   "
zArchiver.print_file_statusc                 C   s   t  }||  || |S r   )ry   add_inclexclZadd_includepaths)Zinclexcl_patternsZinclude_pathsmatcherr   r   r   build_matcher	  s   

zArchiver.build_matcherc                 C   s    t |j|j|j|jd  tS )z@Start in server mode. This command is usually not used manually.)restrict_to_pathsrestrict_to_repositoriesr   r   )r   r  r  r   r   server)   r   r   r   r   r   do_serve  s   zArchiver.do_serveTF)r   r   r   c              	   C   s   |j  }td|  zt||}W n ttfy$   |  t Y S w t	||}||_
|  |jdd t|||dd W d   n1 sJw   Y  |jrft|}t|d  tdt| |jdkrptd	 | jS )
zInitialize an empty repositoryzInitializing repository at "%s"Fcompact)Zwarn_if_unencryptedNwa  
By default repositories initialized with this version will produce security
errors if written to with an older version (up to and including Borg 1.0.8).

If you want to use these older versions, you can disable the check by running:
borg upgrade --disable-tam %s

See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability for details about the security implications.	plaintexta)  
IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
If you used a repokey mode, the key is stored in the repo, but you should back it up separately.
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).
)r   canonical_pathr   r  r"   EOFErrorKeyboardInterruptdestroyr*   rN   r   writecommitr   r%   r$   opencloser   shlexquoteNAMEr   )r   r   r   r   r   r   tam_filer   r   r   do_init  s6   


zArchiver.do_init)r   r   c                 C   s  |j rd}t|ddddddstS |jr+t|j|j|j|jdu|j	fr+| 
d	 tS |j r8|jr8| 
d
 tS |jrE|jsE| 
d tS |jsU|j|j |j|jdsUtS |jdur`|jd |_	|jst j||j |jj|j|j|jptd|j	|j|jd	stS tS )zCheck repository consistencyzThis is a potentially dangerous function.
check --repair might lead to data loss (for kinds of corruption it is not
capable of dealing with). BE VERY CAREFUL!

Type 'YES' if you understand this and want to continue: 	Aborting.Invalid answer, aborting.YESFZ!BORG_CHECK_I_KNOW_WHAT_I_AM_DOINGZ	false_msgZinvalid_msgZtruishretryZenv_var_overrideNze--repository-only contradicts --first, --last, --glob-archives, --prefix and --verify-data arguments.z0--repair does not allow --max-duration argument.z9--repository-only is required for --max-duration support.)repair
save_spacemax_durationr    ts)r'  r   firstlastsort_byglobverify_datar(  )r'  rW   r+   	repo_onlyr   r/  r+  r,  prefixglob_archivesr   r)  archives_onlycheckr(  r*   r   r   r   r-  r)   )r   r   r   r   r   r   r   do_checkA  s<   



zArchiver.do_check)r   c                 C   sF   t |dstd tS |  td t |dr!td|  tS )z%Change repository key file passphrasechange_passphrasez?This repository is not encrypted, cannot change the passphrase.Key updatedfind_keyzKey location: %s)hasattrr   r+   r6  r   r  r8  r)   r   r   r   r   r   r   r   r   do_change_passphraseh  s   


zArchiver.do_change_passphrase)r   r   r   r   c                 C   s|   t |}|  |jr||j tS z|jr ||j W tS ||j W tS  ty=   | 	d|j d t
 Y S w )z$Export the repository key for backup'z!' must be a file, not a directory)r(   Zload_keyblobpaperZexport_paperkeyr   qrZ	export_qrexportIsADirectoryErrorr   r+   r)   r   r   r   managerr   r   r   do_key_exportu  s   
zArchiver.do_key_exportc                 C   s~   t |}|jr|jr| d tS || t	S |js"| d tS |jdkr8tj|js8| d|j  tS || t	S )z%Import the repository key from backupz.with --paper import from file is not supportedz&input file to import key from expected-zinput file does not exist: )
r(   r=  r   r   r+   Zimport_paperkeyosexistsZimport_keyfiler)   rA  r   r   r   do_key_import  s   

	

zArchiver.do_key_import)r   c                 C   sd   | tj}t||}t|}||_|j|_|j	|_	|j
|_
|j|_|j|_|  td tS )zMigrate passphrase -> repokeyr7  )r   rN   MANIFEST_IDr'   detectr&   targetidZrepository_idZenc_keyZenc_hmac_keyZid_keyZ
chunk_seedr6  r   r  r)   )r   r   r   Zmanifest_dataZkey_oldZkey_newr   r   r   do_migrate_to_repokey  s   
zArchiver.do_migrate_to_repokeyc              
      s.   fdd}t dd }dtjv rddg}ng d}|D ]x\}}}}||j|||}	||j |	\}
}}}W d	   n1 sAw   Y  || d
 }t|}|rTdnd}d}t|d|||
 ||||
f  t|d||| ||||f  t|d||| ||||f  t|d||| ||||f  qdS )z4Benchmark Create, Read, Update, Delete for archives.c              	      s  | d }d}t  }  d|d|d |g}t  }|| }|dks'J   d||d |g}  d|d g}	||	  krLdksOJ  J t  }  d||d	 |g}t  }|| }
  d|d	 g}	||	  krdksJ  J t  }  d
d|d g}t  }|| }|dksJ t  }  d|d g}t  }|| }|dksJ ||
||fS )Nz::borg-benchmark-crudz--compression=noner   z--files-cache=disabled1r   2delete3extract	--dry-run)r   r   	do_create
parse_args	do_delete
do_extract)repor   r   r   Zt_startrcZt_end	dt_createZrc1Zrc2	dt_update
dt_extract	dt_deleter   r   r   measurement_run  s6   z3Archiver.do_benchmark_crud.<locals>.measurement_runc           	   	   s   s    zat j| d} t |  |rd n|ttkr ttd | nd| }t|D ]/}t j| d| }|s7|nt |}t	|dd}|
| W d    n1 sRw   Y  q(| V  W t|  d S t|  w )Nzborg-test-data    zfile_%dT)binary)rE  r   joinmakedirslenzeros
memoryviewrangeurandomr~   r  shutilrmtree)	r   countsizerandomZz_buffifnamedatafdr   r   r   
test_files  s   
,z.Archiver.do_benchmark_crud.<locals>.test_filesZ_BORG_BENCHMARK_CRUD_TEST)zZ-TESTr   r   F)zR-TESTr   r   T))zZ-BIG
    F)zR-BIGrr  rs  T)zZ-MEDIUM  @B F)zR-MEDIUMrt  ru  T)zZ-SMALL'  rv  F)zR-SMALLrv  rv  TNg    .Arl  zall-zeroz-%s-%-10s %9.2f MB/s (%d * %s %s files: %.2fs)CRUDr   )r   rE  environr   r   r  r>   r   )r   r   r^  rq  testsr   rj  rk  rl  r   rY  rZ  r[  r\  Ztotal_size_MBZfile_size_formattedcontentfmtr   r]  r   do_benchmark_crud  s*   "

	 zArchiver.do_benchmark_cruddry_run)r   r   r   c                    s  t dd j  fdd} j_ j_ jp" j_ j_ j_ j	_	 j
t }t }td jj  st|| jj j j jdi}t|| jj|d j j j  j j j|| j jd}	t  j  j jp j j j j j!d}
t"|||	j#|	j$ jd	d
}t%|
|||j&|	j# j j j' j jj(d}||	|| W d   j)S 1 sw   Y  j)S |ddd j)S )zCreate new archiveTfallbackc                    s  t  }ztt }||j|jf W n	 ty   Y nw  jj	s>zt jj
}||j|jf W n	 ty=   Y nw td  jrЈ j} j} j} j}szUztdd}	tj jtj|	td}
W n ttfy } zd| jW  Y d }~W S d }~ww |j|||
j|||d}|
 }|dkrd jd | jW S W n ty } zd	|| jW  Y d }~S d }~ww d
} || n j!s׈ j"r j#d urt$ j#nd} j!rztdd}	tj jtj|	td}
W n ttfy } zd| jW  Y d }~S d }~ww |
j}nt%j&j'}t(|dd}t)||D ]f}tj
*|}z-t+d t,|d d dd}W d    n	1 sLw   Y  j-|d d ||| j.d}W n tt/fy~ } z0d	|| d}W Y d }~nd }~ww |dkr0d|  || q+ j!r|
 }|dkrd jd | jS n jD ]}|d
kr j} j} j} j}sz|j||t%j&j'|||d}W n ty } zd}0d	|| W Y d }~nd }~ww d
} || qtj
*|}zHt+d t,|d d dd}W d    n	1 sw   Y   j1r'|jnd }j2|d d || j3 j4 j5|| j.d ||j|jf W q tt/fyg } z0d	|| W Y d }~qd }~ww sƈ j6rv| j7j8dd |  j7|j77  _7t9rd d S | j: j; j<d   j7 j=O  _7 j7rȈ j=rt>t?|d| id d S t@tAtB| tAtCtB| j7tB|tAtDEdd d S d S d S )NzProcessing files ...Tsystem)stdoutenv
preexec_fnzFailed to execute command: %s)r   r   rp  modeusergroupr   z Command %r exited with status %d%s: %srD  
surrogateescape)errorsstatFr   	parent_fdr   follow_symlinksr   r  r   stfsor   read_specialr  Erw  &%s: file changed while we backed it upr   r  r   r  r   r	  exclude_cachesexclude_if_presentkeep_exclude_tagsskip_inodesrestrict_devr  r  finalGot Ctrl-C / SIGINT.commentrJ   r   r   extraborg.output.statsr   )FsetrE  r  rL   addst_inost_devOSErrorr   hostr   r   debugcontent_from_command
stdin_name
stdin_mode
stdin_userstdin_grouprf   
subprocessPopenpathsPIPEro   FileNotFoundErrorPermissionErrorr   r   Zprocess_piper  waitr   r  paths_from_commandpaths_from_stdinZpaths_delimiterrE   r  stdinbufferr   rp   normpathr   rM   _process_anyr  r   r   one_file_system	_rec_walkr  r  r  r   statsshow_progressrn   saver  rJ   r   ra   r`   rY   DASHESr   STATS_HEADERr  r  )r   r   r  r  r  r   r  r  r  r  procer   rX  Z	paths_sepZpipe_binpiper  r   r  r   r	  r   r   r   create_inner   s  












z(Archiver.do_create.<locals>.create_innerzCreating archive at "%s")r   r   Zpermit_adhoc_cacher   r   )r   r   checkpoint_intervalr   noatimenoctimer   chunker_paramsstartstart_monotonicr   r   )r  r  r   r   r   r   nobirthtimeFr   r   add_itemwrite_checkpointr  Z
rechunkify)metadata_collectorr   r   process_file_chunksr  r  r  sparser   r   file_status_printerN)*ry   r  patternsr   r   r   r   r   r   exclude_nodumpr  rK   r   r   r   r  r   	processedr   r   r   no_cache_syncr   r   r   r   r  r   atimer  r  r   r   r  r   r  r  r   r  r  r  r   )r   r   r   r   r   r  t0t0_monotonicr   r   r  cpr  r   r  r   rS    s^   
 
zArchiver.do_createc                C   s  |rdS t |jr|j|||||dS t |jr#|j||||dS t |jre|s4|j||||dS z
t|||dd}	W n t	yI   d}
Y nw t
|	j}
|
r\|j||||	|tdS |j||||dS t |jr|sv|j||||dS |j|||||tdS t |jr|s|j||||dd	S |j|||||tdS t |jr|s|j||||d
d	S |j|||||tdS t |jrdS t |jrdS t |jrdS | d| dS )zO
        Call the right method on the given FilesystemObjectProcessor.
        rD  )r   r  r   r  r   )r   r  r   r  Tr  F)r   r  r   r  r   flagsc)r   r  r   r  Zdev_typebNzUnknown file type: %s)r  S_ISREGst_modeprocess_fileS_ISDIRprocess_dirS_ISLNKZprocess_symlinkrM   r  r   rk   S_ISFIFOprocess_fiforl   S_ISCHRprocess_devS_ISBLKS_ISSOCKS_ISDOORS_ISPORTr   )r   r   r  r   r  r  r   r  r  Z	st_targetspecialr   r   r   r    s\   
zArchiver._process_anyc                C   s  t rt  rdS d}zd}||r0td t|||dd}W d   n1 s*w   Y  n3| d| |js<W dS d}td t|||dd}W d   n1 sUw   Y  t|j	scW dS |j
|jf|
v rnW dS |du pv|j|k}| jrtd! t||dtj@ r| d| 	 W d   W dS W d   n1 sw   Y  t|j	s| j||||||||d	}nt|||tdd
d}|durtd t|t|}W d   n1 sw   Y  |r2t|||}|r2|s(|	r"|s|j|||d |D ]}tj||}| j|||||||||	|
|||d q| d| 	 W d   W dS |sC|sA|j|||d}nd}|rtd tj||d}W d   n	1 s]w   Y  |D ]"}tjtj||j}| j|||j||||||	|
|||d qdW d   n	1 sw   Y  W n ttfy } z|  d|| d}W Y d}~nd}~ww |dkr|  d| |s| || dS dS )z
        Process *path* (or, preferably, parent_fd/name) recursively according to the various parameters.

        This should only raise on critical errors. Per-item errors must be handled within this method.
        NFr  r  xTr  )r   r  r  Zdir_open)r   r  r   r  r  opfstat)r   rp  r  r  rD  scandir)r   rp  r  r  rw  r  )!rn   action_donematchr   rM   r  Zrecurse_dirr  r  r  r  r  r  r|   	UF_NODUMPr  r   rj   r   rE  r  rT   Zprocess_dir_with_fdr   ra  r  r   Zscandir_inorderr  r   r   r   r   )r   r   r  r   r  r   r	  r  r  r  r  r  r  r  r   Zrecurse_excluded_dirr  recurseZchild_fdZ	tag_namesZtag_nameZtag_pathentriesZdirentr  r  r   r   r   r    s   









(
zArchiver._rec_walkc                    s*   r fdd}|S  fdd}|S )Nc                    s8     | jotj| jtjd  }| | |S r   )r  r   rE  sepra  splitr   Zmatchedr	  peek_and_store_hardlink_mastersstrip_componentsr   r   item_filterE  s   *
z*Archiver.build_filter.<locals>.item_filterc                    s     | j}| | |S r   r  r   r   )r	  r  r   r   r  J  s   
r   )r	  r  r  r  r   r  r   build_filterB  s
   	zArchiver.build_filterc                    s   t  dkrtd t jdrtd | |j|j}|j	}|j
}|j}	|j}
|j}|j}g }|  p8|s=ts?i nd  fdd}| |||}|rotdd	d
d}|d t fdd||D }||_nd}|j|d dD ]}|j}|rtj|tj|d |_|js|r|j|d js|d}z	|j||
d W n ty } z| dt |j| W Y d}~nd}~ww |r|j|d jr|rt!"d#t |j z.|	r|j|d|d n!t$%|j&r|'| |j||
dd n|j||
| |||d W qz tt(fy- } z| dt || W Y d}~qzd}~ww |r5|)  |jsxtt*|ddd}|rx|+  |d}z	|j||
d W n tyt } z| dt |j| W Y d}~nd}~ww |sE|, D ]	}| d| q||r|)  | j-S )zExtract archive contentsasciiz_Warning: File system encoding is "ascii", extracting non-ascii filenames will not be supported.)linuxfreebsdZnetbsdZopenbsddarwinz^Hint: You likely need to fix your locale setup. E.g. install locales and use: LANG=en_US.UTF-8Nc                    sZ   t rr%|s't| jr)| ddr#d| vr+| dd f | d< d S d S d S d S d S d S NZhardlink_masterTsourcechunksr   )r   rP   r  r   r   hardlink_masterspartial_extractr   r   r  f  s   	
z<Archiver.do_extract.<locals>.peek_and_store_hardlink_mastersz%5.1f%% Extracting: %s皙?rQ  r   stepmsgidz^Calculating total archive size for the progress indicator (might take long for large archives)c                 3       | ]}|  V  qd S r   get_sizer   r  r   r   r   w  r   z&Archiver.do_extract.<locals>.<genexpr>Tr  Zpreloadr  )r  r  r   )r  piF)r  Zrestore_attrs)r  r  r  Zstripped_componentsoriginal_pathr  z%Setting directory permissions %3.0f%%zextract.permissionstotalr   r  #Include pattern '%s' never matched.).r  getfilesystemencodingr   r   platform
startswithr
  r  r  r   r   r  r  r  r  emptyr   r  r_   outputsum
iter_itemsr  r   rE  r  ra  r  popextract_itemr   r   rB   r  r  r  r  r  r  appendr   finishrc  showget_unmatched_include_patternsr   )r   r   r   r   r   r   r	  r   r   r  r  r  r  dirsr  filterr  extracted_sizer   	orig_pathZdir_itemr  patternr   r  r   rV  P  s   




 


 zArchiver.do_extractc           
      C   s   |j | _ |jdkrt|jddn|j}t|jd}|jdk}t|||dd}	| |||	 W d   | jS 1 s:w   Y  | jS )z$Export archive contents as a tarballautoF
decompresswbrD  streamZstream_closeZinboundN)r   
tar_filterrq   tarfilerh   rg   _export_tarr   )
r   r   r   r   r   r   r.  	tarstreamtarstream_close_streamr   r   r   do_export_tar  s   

zArchiver.do_export_tarc                    sx   |j|j}|j}|j}|j|  pri nd fdd}||}tj	|dtj
d}	|rUtddddd	 tfd
d |D }
|
_nd  fddfdd} j|ddD ]1}|j}rtj|tjd  |_|||\}}|r|rtdt| |	|| qpr  |	  | D ]}d| qjS )Nc                    sV   r!|s#t | jr%| ddr'd| vr)| dd f | d< d S d S d S d S d S d S r  )rP   r  r   r   r  r   r   r    s   
z=Archiver._export_tar.<locals>.peek_and_store_hardlink_masterszw|)fileobjr  formatz%5.1f%% Processing: %sr  rQ  r  zCalculating sizec                 3   r  r   r  r   r  r   r   r     r   z'Archiver._export_tar.<locals>.<genexpr>c                    sH   j jdd | jD dd}r t| jg t| fddS t|S )zY
            Return a file-like object that reads from the chunks of *item*.
            c                 S   s   g | ]\}}}|qS r   r   )r   Zchunk_id_r   r   r   
<listcomp>  s    zEArchiver._export_tar.<locals>.item_content_stream.<locals>.<listcomp>T)Zis_preloadedc                    s   j t|  dS )N)Zincreaser  )r+  rc  )
read_bytes)r  r  r   r   <lambda>  s    zCArchiver._export_tar.<locals>.item_content_stream.<locals>.<lambda>)ZpipelineZ
fetch_manyr  rB   r   rc   )r   Zchunk_iterator)r   r  )r  r   item_content_stream  s   z1Archiver._export_tar.<locals>.item_content_streamc                    s  d}t  }| j|_| jd |_t| j|_| j|_| j	|_	| j
p#d|_| jp)d|_d|_t| j}|tjkrt j|_d| v rtj| jtjd } du rW|}n | jd|f\}}|rot j|_||_||fS |dur|| _|  |_| }d| jf | dp|< ||fS |  |_| }||fS |tjkrt j|_||fS |tjkrt j |_| j|_||fS |tj!krt j"|_t#| j$|_%t&| j$|_'||fS |tj(krt j)|_t#| j$|_%t&| j$|_'||fS |tj*krt j+|_||fS ,dt-| j| t.t/ d|fS )ad  
            Transform a Borg *item* into a tarfile.TarInfo object.

            Return a tuple (tarinfo, stream), where stream may be a file-like object that represents
            the file contents, if any, and is None otherwise. When *tarinfo* is None, the *item*
            cannot be represented as a TarInfo object and should be skipped.
            Ng    eA r  z+%s: unsupported file type %o for tar export)0r9  TarInfor   r   mtimer  S_IMODEr  uidgidr  unamer  gnamelinknameS_IFMTS_IFREGREGTYPEr   rE  r  ra  r  r  r   LNKTYPEr  r  rk  S_IFDIRDIRTYPES_IFLNKSYMTYPES_IFBLKBLKTYPEmajorZrdevdevmajorminordevminorS_IFCHRCHRTYPES_IFIFOFIFOTYPEr   rB   r/   r*   )r   r  r7  tarinfoZmodebitsr  rN  r  )r  rE  r   r  r   r   item_to_tarinfo  sl   







z-Archiver._export_tar.<locals>.item_to_tarinfoTr  r   r  )r
  r  r  r   r   r  r#  r  r9  r  
GNU_FORMATr_   r$  r%  r&  r  r   rE  r  ra  r  r  r  r  rB   addfiler*  r  r,  r   r   )r   r   r   r;  r	  r   r   r  r.  tarr/  rb  r   r0  ra  r7  r1  r   )r   r  rE  r  r  r   r  r   r:    sF   
L
zArchiver._export_tarc                 C   s  dd }dd }|j r|n|}|}	t||||j|jd}
|	jd}|
jd}|jr.d}n|durF|durFt|t|k}|sE| d	 nd
}| d | 	|j
|j}tj|	|
|||jd}dd |D }|jrnt|}|D ]\}}||t| qp| D ]}| d| q| jS )zDiff contents of two archivesc                 S   s(   t tj|dd | D ddtd d S )Nc                 S   s   g | ]\}}|qS r   r   r   jr   r   r   r   rB  ]      z?Archiver.do_diff.<locals>.print_json_output.<locals>.<listcomp>)r   changesT)	sort_keyscls)r   r   r  rr   diffr   r   r   r   print_json_output\  s   (z+Archiver.do_diff.<locals>.print_json_outputc                 S   s$   t dddd | D | d S )Nz	{:<19} {} c                 S   s   g | ]\}}|qS r   r   rf  r   r   r   rB  `  rh  z?Archiver.do_diff.<locals>.print_text_output.<locals>.<listcomp>)r   r@  ra  rl  r   r   r   print_text_output_  s   $z+Archiver.do_diff.<locals>.print_text_outputr   r  TNzC--chunker-params are different between archives, diff will be slow.Fz--chunker-params might be different between archives, diff will be slow.
If you know for certain that they are the same, pass --same-chunker-params to override this check.)can_compare_chunk_idscontent_onlyc                 s   s&    | ]\}}|j s|| fV  qd S r   )equalri  )r   r   rm  r   r   r   r   |  s   $ z#Archiver.do_diff.<locals>.<genexpr>r  )
json_linesr   archive2r   metadatar   same_chunker_paramsrd   r   r
  r  r  Zcompare_archives_iterrs  sortsortedrB   r,  r   )r   r   r   r   r   r   rn  rp  Zprint_outputZarchive1rv  Zcp1Zcp2rr  r	  Zdiffsr   rm  r1  r   r   r   do_diffW  s8   

zArchiver.do_diff)r   r   r   c                 C   s.   | |j |  |jdd |  | jS )zRename an existing archiveFr  )renamer   r  r  r   )r   r   r   r   r   r   r   r   r   r   	do_rename  s
   zArchiver.do_renamec                C   sf   d}t ot  }|s|r1t | j |kr1|rtd |  d}t | _|r1t   td |S )NFz5checkpoint requested: starting checkpoint creation...Tz3checkpoint requested: finished checkpoint creation!)rn   Zaction_triggeredr   r   r   r   r  Zaction_completed)r   checkpoint_funcr  checkpointedZsig_int_triggeredr   r   r   maybe_checkpoint  s   


zArchiver.maybe_checkpointc                 C   sj   t |j|j|jdu|jf}|jjp|j}|j| _|r%|r%| 	d | j
S |s)|r/| ||S | ||S )z)Delete an existing repository or archivesNzFMixing archive filters and explicitly named archives is not supported.)r   r+  r,  r1  r2  r   r   archivesr   r   r   _delete_archives_delete_repository)r   r   r   Zarchive_filter_specifiedZexplicit_archives_specifiedr   r   r   rU    s   
zArchiver.do_deletec                    s4   j }ttjjf\} jjs jr+t j} jjr&|	d jj t
|}nd _t
dd j D }|s@| jS  jdkrd}td}t|dD ]C\}	}
zj|
}W n tyz   t| _td	|
 d
|	 dt| d Y qQw d}| jr|rdnd}||t||	t| qQ|rtd | jS |r  jdd td | jS td | jS t jd}t | j!| j" jd fdd}|rdnd}d}td}d}t|dD ]e\}	}
t#rt#$ r nZzj|
 }W n ty   t||
|	t| Y qw | jr(||t||	t| |sQt%||
 j&d}|j'| j! jd | j(| j)d}|rMdn|d }qt#r[| *d n|dkrc|   j+rt,t-t.|j/jd|dt0t-td d! W d"   | jS W d"   | jS 1 sw   Y  | jS )#zDelete archivesr   Tc                 s       | ]}|j V  qd S r   r   r   r  r   r   r   r         z,Archiver._delete_archives.<locals>.<genexpr>r   Fr   r   zArchive z not found (/z).zWould delete: {} ({}/{})zDeleted archive: {} ({}/{})zFinished dry-run.r  z5Done. Run "borg check --repair" to clean up the mess.zAborted.r   )r   r   r   c                      $      jd jd   d S NF)r  r(  r  r  r(  r   r   r   r   r   r   r   r~       z2Archiver._delete_archives.<locals>.checkpoint_funcz Would delete archive: {} ({}/{})zDeleting archive: {} ({}/{})zArchive {} not found ({}/{}).r   r   )r   forcedr~  r  r  Deleted data:labelr  r  r  N)1r  rN   r   	OperationDELETEr   r   r  r   insertr   consider_checkpointslist_consideringr   r  r  r  	enumerater'  KeyErrorr*   r   r   rc  r   r  r@  r@   r  r  r   r   r   r   r   rn   r  r   r   rO  r  r  r   r  rY   r  r  summaryr   )r   r   r   r  r   r  archive_namesZdeletedZlogger_listrm  archive_nameZcurrent_archiver   r  r~  Z
msg_deleteZmsg_not_founduncommitted_deletesarchive_infor   r  r   r  r   r    s   



&






(
((zArchiver._delete_archivesc                 C   s  |j }|j}|js|jdkrt|j}|j }g }zt	|tj
\}}	t|j}
|d|
 d W n tyC   d}
|d Y nw |t |d|  |d|  | jr|d |d	 |
dur|
dkr|jjd
gdD ]	}|t| qvn|d n|d |t |d d|}t|ddddddst| _| jS |s|  td |st| ntd td|rdnd  |st| td | jS td | jS )zDelete a repositoryr   zHYou requested to completely DELETE the following repository *including* z archives it contains:NzdYou requested to completely DELETE the following repository *including* all archives it may contain:zRepository ID: z
Location: rF  z	Archives:r*  r-  z/This repository seems to not have any archives.zXThis repository seems to have no manifest, so we can't tell anything about its contents.z8Type 'YES' if you understand this and want to continue: r  r!  r"  r#  FZ"BORG_DELETE_I_KNOW_WHAT_I_AM_DOINGr%  zRepository deleted.zWould delete repository.zWould %s security info.keeprO  zCache deleted.zWould delete cache.)r  keep_security_info
cache_onlyr  rC   rK  	_locationr  rN   r   r   rc  r  r)  r.   r  r   r   r@   ra  rW   r+   r   r  r   r  r   r   )r   r   r   r  r  rK  r   r   r   r   Z
n_archivesr  r   r   r   r    sh   

















zArchiver._delete_repositoryc                 C   sv   ddl m}m} |du r| d|  | jS tj|jr+t	|jtj
tjB tjB s6| d|j  | jS | |S )z:Mount archive or an entire repository as a FUSE filesystemr   )llfuseBORG_FUSE_IMPLNz=borg mount not available: no FUSE support, BORG_FUSE_IMPL=%s.z+%s: Mountpoint must be a writable directory)Z	fuse_implr  r  r   r   rE  r   isdir
mountpointaccessR_OKW_OKX_OK	_do_mount)r   r   r  r  r   r   r   do_mountA  s   *
zArchiver.do_mountc              	   C   s   ddl m} t||d9}||||||}td z||j|j|j W n t	y2   t
| _Y n
w W d    | jS W d    | jS 1 sHw   Y  | jS )Nr   )FuseOperations)Zdecrypted_cachezMounting filesystem)Zfuser  r   r   r  mountr  options
foregroundRuntimeErrorr+   r   )r   r   r   r   r   r  Zcached_repoZ
operationsr   r   r   r  P  s"   



zArchiver._do_mountc                 C   s
   t |jS )zun-mount the FUSE filesystem)ri   r  r  r   r   r   	do_umount^  s   
zArchiver.do_umountc                 C   sT   |j jr|jr| d | jS | ||||S |jr"| d | jS | ||||S )z#List archive or repository contentszKThe --json option is only valid for listing archives, not archive contents.zQThe --json-lines option is only valid for listing archive contents, not archives.)r   r   r   r   r   _list_archiveru  _list_repositoryr:  r   r   r   do_listb  s   

zArchiver.do_listc                    s   |   j j jd ur jn jrdnd fdd}trKt| jd}|| W d    | j	S 1 sCw   Y  | j	S |d d | j	S )Nz
{path}{NL}z<{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}c                    sX   t  jj|  jd}t| jd}|fddD ]}tj	|
| qd S )Nr  )ru  c                    s     | jS r   r  )r   )r	  r   r   rD  ~  s    z=Archiver._list_archive.<locals>._list_inner.<locals>.<lambda>)r   r   r   r   r;   ru  r&  r  r  r  format_item)r   r   	formatterr   r   r@  r   r   r	  r   r   r   _list_innery  s   z+Archiver._list_archive.<locals>._list_innerr   r   )
r
  r  r  r@  shortr;   Zformat_needs_cacher   r   r   )r   r   r   r   r   r  r   r   r  r   r  p  s    

	


zArchiver._list_archivec           	      C   s   |j d ur	|j }n|jrd}nd}t|||||j|jd}g }|j|D ]}|jr3||| q%t	j
|| q%|jrJtt|d|id | jS )Nz{archive}{NL}z{archive:<36} {time} [{id}]{NL})r   r   r  )r  )r@  r  r<   r   r   r  r  r)  Zget_item_datar  r  r  r  ra   r`   r   )	r   r   r   r   r   r@  r  output_datar  r   r   r   r    s    

zArchiver._list_repository)r   r   c                 C   sF   t |jj|j|j|jdu|jfr| |||||S | |||||S )z,Show archive details such as disk space usedN)	r   r   r   r+  r,  r1  r2  _info_archives_info_repository)r   r   r   r   r   r   r   r   r   do_info  s   "zArchiver.do_infoc              
   C   s  dd }|j jr|j jf}nd|_tdd |j|D }g }t|dD ]S\}	}
t||||
||j|j	d}|
 }|jrC|| n$tt|d d	|d< ||d
 |d
< ttd jdd|i| | jrl n|jsxt||	 rxt  q%|jrtt||d|id | jS )Nc                 S   s   t ddd | D S )Nro  c                 s   s    | ]}t |V  qd S r   )r  r  r  r   r   r   r     r   zBArchiver._info_archives.<locals>.format_cmdline.<locals>.<genexpr>)rB   ra  )cmdliner   r   r   format_cmdline  s   z/Archiver._info_archives.<locals>.format_cmdlineTc                 s   r  r   r  r  r   r   r   r     r  z*Archiver._info_archives.<locals>.<genexpr>r   )r   r   r   Zduration)secondsZcommand_lineaF  
                Archive name: {name}
                Archive fingerprint: {id}
                Comment: {comment}
                Hostname: {hostname}
                Username: {username}
                Time (start): {start}
                Time (end): {end}
                Duration: {duration}
                Number of files: {stats[nfiles]}
                Command line: {command_line}
                Utilization of maximum supported archive size: {limits[max_archive_size]:.0%}
                ------------------------------------------------------------------------------
                                       Original size      Compressed size    Deduplicated size
                This archive:   {stats[original_size]:>20s} {stats[compressed_size]:>20s} {stats[deduplicated_size]:>20s}
                {cache}
                r   r  r  r   )r   r   r  r   r  r  r  r   r   r   r  r   r)  r=   r   r   textwrapdedentstripr@  r   rc  ra   r`   )r   r   r   r   r   r   r  r  r  rm  r  r   r  r   r   r   r    s@   

zArchiver._info_archivesc                 C   s   t ||d|jjid}|jrt| | jS d}|jdv r!|d7 }n|d|j 7 }|jdr6|d|  7 }||d	< tt	
d
 jdt|j|j d| tt tt tt| | jS )NZsecurity_dirr  zEncrypted: )r  ZauthenticatedZNozYes (%s)zkey filez
Key file: %s
encryptionz
            Repository ID: {id}
            Location: {location}
            {encryption}
            Cache: {cache.path}
            Security dir: {security_dir}
            )rK  r   r   )r`   Zsecurity_managerdirr   ra   r  r"  r8  r   r  r  r  r@  rC   rK  r  r  r  r  r   r   )r   r   r   r   r   r   r  r  r   r   r   r    s2   


	
zArchiver._info_repository)r   r   c              
      s,  t  j j j j j j j jfs| 	d | j
S  jdur' jd  _d}jj jdd| dgdd}td	| jfd
d|D |r\r\|d d u r\dd }ng }tfdd|D }g }	i }
 jr{|	t| j|
7 }	t D ]}t |d}|dur|	t||||
7 }	qt|B t|	t|B  }t jd}t|| j jd։ fdd}td}t|}d}d}tt|ddd}|D ]s}t rt ! r nj||v r|"   j#rd}nJ|d7 }d||f }t$||j% j&d}|j'| j(d | j)| j*d}|rdn|d }n|j%r(d}ndj+|
|j, d |
|j, d d} j-rI|.dj+|t/|d  q|0  t rW| 	d! n|dkr_|   j1rt2t3t4|j5j+d"|d#t6t3td$d% W d   | j
S W d   | j
S 1 sw   Y  | j
S )&z6Prune repository archives according to specified ruleszAt least one of the "keep-within", "keep-last", "keep-secondly", "keep-minutely", "keep-hourly", "keep-daily", "keep-weekly", "keep-monthly" or "keep-yearly" settings must be specified.Nr    z\.checkpoint(\.\d+)?Tz(%s)?\Zr*  )r.  r  Z	match_endr-  reversez(%s)\Zc                    s   g | ]	} |j r|qS r   r  r   arch)is_checkpointr   r   rB        z%Archiver.do_prune.<locals>.<listcomp>r   r   c                    s   g | ]}| vr|qS r   r   r  )checkpointsr   r   rB    s    r  )r   r   c                      r  r  r  r   r  r   r   r~  )  r  z*Archiver.do_prune.<locals>.checkpoint_funcr   zPruning archives %3.0f%%pruner  zWould prune:zPruning archive (%d/%d):rq  )r  r  zKeeping checkpoint archive:z&Keeping archive (rule: {rule} #{num}):)rulenumz{message:<40} {archive})messager   r  r  r  r  r  )7r   secondlyminutelyhourlydailyweeklymonthlyyearlywithinr   r   r1  r2  r  r   recompilesearchr  rG   rI   keysr   rH   r   r   r   r   r  r  rc  r_   rn   r  r+  r  r   r   r   rO  r  r  r  r@  rK  r   r  r@   r*  r  rY   r  r  r  r   )r   r   r   r   r   Zcheckpoint_reZarchives_checkpointsZkeep_checkpointsr  r  Zkept_becauser  r  Z	to_deleter  r~  Zlist_loggerZto_delete_lenZarchives_deletedr  r  r   Zlog_messager  r   )r   r   r  r  r   r   r   do_prune  s   







3
33zArchiver.do_prune)tamdisable_tamarchives_tam)r   r   r   r   c              
   C   s  |j rtj|tjjf|jd\}}t|||}t }|jj	dgdD ]g}|j
}t|}	||}
|||
}|j|dd\}}}|st|d}dd |jD |_|j| dd	}||}|||| ||| ||jf|j|j< td
|	 dt| d q#td|	  q#|  |jdd |  W d   | j4S 1 sw   Y  | j4S |jr(tj|tjjf|jd\}}|jr|jddstd |jj	dgdD ]}tt| qd|jd< |  |jdd |jst |drd|_|!|j" td t |drtd|#  t|s%t$|}t%|d&  td | j4S |j'rytj|tj(dd\}}t|rCt)*t$| |jrgt |drgd|_|!|j" td t |drgtd|#  d|jd< |  |jdd | j4S t+|j,j-dd}z|j.|j/|j0|j1d W n t2y } ztd|  W Y d}~nd}~ww t3|j,j-dd}z|j.|j/|j0|j1d W | j4S  t2y } ztd|  W Y d}~| j4S d}~ww )z,upgrade a repository from a previous version)Zforce_tam_not_requiredr*  r  T)Zinternal_dictc                 S   s   g | ]}t |qS r   )rs   )r   argr   r   r   rB  l  rh  z'Archiver.do_upgrade.<locals>.<listcomp>s   archivecontextzAdded archive TAM:   z -> []zArchive TAM present: Fr  Ns   tam_requiredzManifest contents:r6  r7  r8  zKey location:r  zUpdated security database)r   )inplacer   zwarning: %s)5r  rN   r   r  CHECKforcer   r   r  r   rK  r@   r   decryptZunpack_and_verify_archiver{   r  Zpack_and_authenticate_metadataas_dictid_hashZ	add_chunkZchunk_decrefr*  r   r   rC   r  r  r  Ztam_verifiedconfigr%   r9  r6  Z_passphraser8  r$   r  r  r  r   rE  unlinkr   r   r   upgrader  r  r   NotImplementedErrorr   r   )r   r   r   r   r   r   r  r  Z
archive_idZarchive_formattedcdataro  r   ZverifiedrA  Znew_archive_idr  r  rW  r  r   r   r   
do_upgrade]  s   




DD



zArchiver.do_upgrade)r   r   r   c                 C   sR  |  |j|j}|j| _|j| _|jdk}|jdk}t|||||f|j|j|j	|j
|j|||j|j| j|j|j|jd}	|jjrb|jj}
|	|
rS| d|
 | jS |	|
|j|jsa| d n3|jduro| d | jS |jjdgd	D ]}|j}
|	|
rqwtd
|
 |	|
|jstd|
 qw|js|   |j!dd |!  | jS )zRe-create archivesneveralways)r  r  r  r  r   
recompressalways_recompressr   r  r  r  r  rJ   z;Refusing to work on temporary archive of prior recreate: %sz~Nothing to do. Archive was not processed.
Specify at least one pattern, PATH, --comment, re-compression or re-chunking option.Nz(--target: Need to specify single archiver*  r  Z
Processingz=Skipped archive %s: Nothing to do. Archive was not processed.Fr  )"r
  r  r  r   r   r  r   r  r  r  r  r   r   r  r  r  r  rJ   r   r   Zis_temporary_archiver   r   recreater  rJ  r  r   r   r   r   r  r  r  )r   r   r   r   r   r   r	  r  r  Z	recreaterr   r   r   r   r   do_recreate  sL   

	





zArchiver.do_recreatec           
   	   C   s   |j | _ |j| _|jdkrt|jddn|j}t|jd}|jdk}t|||dd}	| ||||||	 W d   | jS 1 sAw   Y  | jS )z&Create a backup archive from a tarballr2  Tr3  rbrD  r6  N)	r   r   r8  rq   r9  rh   rg   _import_tarr   )
r   r   r   r   r   r   r.  r;  r<  r=  r   r   r   do_import_tar  s   

zArchiver.do_import_tarc                 C   sL  t  }t }t||||jj|d|j|j|j|||j	d}	t
|||	j|	j|jdd}
t|||
j|	j|j|j|j	|j| jd	}tj|d|jd}	 | }|sOn~| rf|j|dtj|d	}|	j jd
7  _n_| rt|j|dtjd}nQ| r|j|dtj d}nC|! r|j|dtjd}n5|" r|j#|dtj$d}n'|% r|j#|dtj&d}n|' r|j(|dtj)d}nd}| *d|j+|j, | ||j+ qH|-  |jr|	jj.dd |	 j|j7  _|	j/|j0|j1d | j|j2O  _|jr$|j2rt3t4|	j5|	j6d|	id d S t7t8t9|	t8t:t9|	jt9|	j6t8t;<dd d S d S )NT)r   r   r  r   r  r  r  r   Fr  )	r   r   r  r  r  r  r   r   r  zr|)r?  r  ignore_zerosA)ra  r   r   re  r   d)ra  r   r   shr  r  fr  z%s: Unsupported tarinfo type %sr  r  r   r  r  r  )=rK   r   r   r   r   r   r  r   r  r   r   r  r  r   r  r   r  r9  r  r  nextisregr  r  rP  r  Znfilesr  r  rS  issymZprocess_linkrU  islnkisblkr  rW  ischrr]  isfifor  r_  r   r   r   r  r  r  r  rJ   r   ra   r`   r   r   rY   r  r   r  r  r  )r   r   r   r   r   r   r;  r  r  r   r  Ztfore  ra  r   r   r   r   r    s   

zArchiver._import_tar)r   r   c              	   C   sn   | tj}|tj| t|dr|j  tdd}ztj	|j
g|j |dW |jdd S |jdd w )z:run a user specified command with the repository lock heldioTr  )r  Fr  )r   rN   rH  putr9  r  Zclose_segmentrf   r  callcommandr   r  )r   r   r   ro  r  r   r   r   do_with_lock)  s   



zArchiver.do_with_lockc                 C   s:   | tj}|tj| |jd }|jd||jd tS )z'compact segment files in the repositoryd   T)r  	thresholdcleanup_commits)r   rN   rH  r  r  r  r  r)   )r   r   r   ro  r  r   r   r   
do_compactG  s
   
zArchiver.do_compactc              
      s  ddd}ddd} fdd}|j s>|jdu r | d	 | jS z
|jd
\}}W n ty=   |jr6dp7d}|j}Y nw |jr\t tj	j
f\}}	t || j t |	|| jd}
z|jrp|
j  |
jj}|
jj}|}n j} fdd}|}|jr|||dd ||| t||dkr|| |  n\|j r|| nT|jr||||j || vr|| ||||j |  n3z
t||| W n( tjtjfy } zt|t j!d t"W  Y d}~W |jr|
#  S S d}~ww t$W |jr|
#  S S |jr|
#  w w )z@get, set, and delete values in a repository or cache config fileNTc                 S   s<  | dvrt d|dv r$|r"zt| W d S  t y!   t dd w d S |dv re|r_zt| W n t y<   t dd w |dkrOt|tdk rMt dd S |d	krat|tkrct d
t d S d S d S |dv rw|rs|dvrut dd S d S |dv r|rzt|}W n   t dd t|dkrt dd S d S t d)Nr   Invalid section)segments_per_dirlast_segment_checkedzInvalid value)max_segment_sizeadditional_free_spacer   r   r   z"Invalid value: storage_quota < 10Mr  z%Invalid value: max_segment_size >= %d)r   )0rM  )rK  z$Invalid value, must be 64 hex digits    Invalid name)
ValueErrorintr?   MAX_SEGMENT_SIZE_LIMITr   rc  )sectionr   valuecheck_valueZbin_idr   r   r   repo_validateU  sT   


z)Archiver.do_config.<locals>.repo_validatec                 S   s4   | dvrt d|dv r|rt| d S d S t d)Nr  r  )Zprevious_locationr  )r  r4   )r!  r   r"  r#  r   r   r   cache_validatex  s   z*Archiver.do_config.<locals>.cache_validatec                    s   dt tt td j jd}td dD ]&}| jd|dd}|d u r2||}|d u r2td	| t| d
|  qdD ]}| jd|d d}|d u rMq>t| d
|  q>d S )NrM  r  )versionr  r  r  r   r   z[repository])r&  r  r  r   r  r   rK  r   Fr  zFThe repository config is missing the %s key which has no default valuez = )r  )r   ZDEFAULT_SEGMENTS_PER_DIRr   r   r   r   r   r-   )r  Zdefault_valuesr   r"  r  r   r   list_config  s*   
z'Archiver.do_config.<locals>.list_configz No config key name was provided..r   r   r  c                      s      j jS r   )Zsave_configr   r  r   r  r   r   rD    s    z$Archiver.do_config.<locals>.<lambda>F)r#  r   r   )NT)%r   r   r   r   r  r  r   rN   r   r  WRITEr   r   r   Zcache_config_configr  r  rO  remove_optionrc  r  remove_sectionr"  sectionsadd_sectionr  r   r   configparserNoOptionErrorNoSectionErrorr  r  r*   r  r)   )r   r   r   r$  r%  r'  r!  r   r   r   r   r  r  validater  r   r  r   	do_configQ  sp   

#	










zArchiver.do_configc                 C   s&   t t  t dtj t dt  tS )z6display system information for debugging / bug reportszCRC implementation:zProcess ID:)r   rX   r   r   r}   r)   r  r   r   r   do_debug_info  s   
zArchiver.do_debug_infoc              	   C   s   t ||||jj|jd}t|jjD ]4\}}||||}d|t	|f }	t
d|	 t|	d}
|
| W d   n1 sAw   Y  qt
d tS )zAdump (decrypted, decompressed) archive items metadata (not: data)rq  z%06d_%s.itemsDumpingr5  NDone.)r   r   r   r   r  rw  itemsr  r   rC   r   r  r  r)   )r   r   r   r   r   r   rm  item_idro  filenamerp  r   r   r   do_debug_dump_archive_items  s   
z$Archiver.do_debug_dump_archive_itemsc                    s   z|j  tjj  W n ty   tjjw dfdd fdd}tj	d}|| W d   t
S 1 sDw   Y  t
S )z)dump decoded archive metadata (not: data)   c                    s   t jtj|  dd  dS )Nindentro  )r1  )r  r=  r   r  )r  r<  r   r   	do_indent  s   z1Archiver.do_debug_dump_archive.<locals>.do_indentc                    s,  |  d |  dtjj d  |  d |  t  |  d  d  d }tj	|t
d}|  d |  t| |  d |  d tjd	t
d
}d}|d D ]*}||}|| |D ]}t|}|r|d	}n|  d |  | qqq_|  d |  d d S )Nz{
z    "_name": z,
z    "_manifest_entry":
s   idobject_hookz    "_meta":
z    "_items": [
F)use_listr@  Ts   itemsr  z    ]
}
)r  r   r  r   r   rD   r  r   rm   unpackbrQ   ZUnpackerfeed)rp  ro  Zarchive_org_dictZunpackerr+  r8  r   )archive_meta_origr   r>  r   r   r   r   r$    s2   








z.Archiver.do_debug_dump_archive.<locals>.outputr  N)r  Zget_raw_dictrA   r   r   r  r   ZDoesNotExistrh   r   r)   )r   r   r   r   r   r$  rp  r   )rD  r   r>  r=  r   r   r   do_debug_dump_archive  s    

zArchiver.do_debug_dump_archivec                 C   sh   | d||j}ttj|td}t|jd}t	j
||dd W d   tS 1 s-w   Y  tS )z dump decoded repository manifestNr?  r  r;  r<  )r  r   rH  rD   rm   rB  rQ   rh   r   r   dumpr)   )r   r   r   r   r   ro  metarp  r   r   r   do_debug_dump_manifest  s   
zArchiver.do_debug_dump_manifestc              	      sX  ddl m} d fdd	}|jrk| D ]\}}}}}	|tkr&|||  nqd}
|j|j|jdD ]7\}}}}}	|tkrH||
||d||	d	 n|tkrW||
|dd
||	d	 n|tkre||
ddd||	d	 |
d7 }
q2n;|j	ddd}|
|d }||| d}d}
	 |jt|d}|sn|d }|D ]}|
|}||
|| |
d7 }
qqtd tS )zOdump (decrypted, decompressed) repo objects, repo index MUST be current/correctr   key_factoryNc                    s   |d ur|t jkr|nd } ||}nd}|d u rdnd| }|d ur*dt| nd}	|d ur6dt| nd}
|d urBdt| nd}d| |	|
||f }td| t|d}|| W d    d S 1 shw   Y  d S )N    rF  rA  z%08d%s%s%s%s.objr5  r5  )rN   rH  r  r   rC   r   r  r  )rm  rK  r  tagsegmentoffsetgive_idro  tag_strZsegment_strZ
offset_strZid_strr9  rp  r   r   r   decrypt_dump(  s   
"z6Archiver.do_debug_dump_repo_objs.<locals>.decrypt_dumpr   )rM  rN  r  )rL  rM  rN  delr  limitmarkerTr  r6  )NNN)
crypto.keyrJ  ghostZscan_low_levelr   rM  rN  r   r   r   r   scanr   r   r)   )r   r   r   rJ  rR  rK  r  rL  rM  rN  rm  idsrV  resultr   rQ  r   do_debug_dump_repo_objs#  sF   
 




	z Archiver.do_debug_dump_repo_objsc              	      s  d  fdd}|j }z"|drt|dd }n|dr(|dd  }ntdW n ttfy:   d}Y nw |sD| d	 tS d
dlm	} |j
d
dd}||d }|||}d}	d}
d}d}	 |jt|	d}|spn|d }	|D ]}||}|tjkr|nd}|||}|
t|d
  d |dt|d
   }||v r|
t|d
    d |dt|d
     }||}d|| | f }||||| ||}|r||}d|| |f }||||| ||}}
|d
7 }|d dkrtd|  qvqftd tS )zMsearch for byte sequences in repo objects, repo index MUST be current/correctr  c              
      sZ   ||  | }||t | |t |    }td| | | | ||| d S )Nz{}: {} {} {} == {!r} {!r} {!r})rc  r   r@  hex)r  wantedro  rN  beforeafterr  r   r   print_finding`  s
    
z9Archiver.do_debug_search_repo_objs.<locals>.print_findingzhex:r;  Nzstr:zunsupported search termz6search term needs to be hex:123abc or str:foobar styler   rI  rT  r   rK  Tr  z
%d %s | %sz	%d %s #%drv  z%d objects processed.r6  )r^  r"  r   encoder  UnicodeEncodeErrorr   r+   rW  rJ  r   r   rY  r   rN   rH  r  rc  findr]  rj  r   r)   )r   r   r   ra  r^  rJ  rZ  r  r   rV  Z	last_dataZlast_idrm  r[  rK  rO  ro  Zboundary_datarN  r  rj  r   r  r   do_debug_search_repo_objs[  sh   




*2



z"Archiver.do_debug_search_repo_objsc              
   C   s   |j }zt|}t|dkrtdW n ty1 } ztd|t|f  tW  Y d}~S d}~ww z||}W n tj	yK   td|  t Y S w t
|jd}|| W d   n1 sbw   Y  td|  tS )z>get object contents from the repository and write it into filer  #id must be 256bits or 64 hex digitsobject id %s is invalid [%s].Nobject %s not found.r5  zobject %s fetched.)rK  r   rc  r  r   r   r+   r   r   ObjectNotFoundr  r   r  r)   )r   r   r   hex_idrK  errro  r  r   r   r   do_debug_get_obj  s,   zArchiver.do_debug_get_objc                 C   sN   t |jd}| }W d   n1 sw   Y  ||}t|  tS )z!compute id-hash for file contentsr  N)r  r   readr  r   r]  r)   )r   r   r   r   r   r  ro  rK  r   r   r   do_debug_id_hash  s   

zArchiver.do_debug_id_hashc              
   C   s   t |jd}| }W d   n1 sw   Y  |j}zt|}t|dkr,tdW n tyK } ztd|t|f  t	W  Y d}~S d}~ww |
|| td|  |jdd tS )	z%put file contents into the repositoryr  Nr  rf  rg  zobject %s put.Fr  )r  r   rm  rK  r   rc  r  r   r   r+   r  r  r)   )r   r   r   r  ro  rj  rK  rk  r   r   r   do_debug_put_obj  s$   
zArchiver.do_debug_put_objc              	   C   s   d}|j D ]7}zt|}W n ty   td|  Y qw z|| d}td|  W q tjy<   td|  Y qw |rE|jdd td tS )z3delete the objects with the given IDs from the repoFobject id %s is invalid.Tzobject %s deleted.rh  r  r6  )	rZ  r   r  r   rO  r   ri  r  r)   )r   r   r   modifiedrj  rK  r   r   r   do_debug_delete_obj  s$   

zArchiver.do_debug_delete_obj)r   r   r   r   c           	   	   C   s|   |j D ]8}zt|}W n ty   td|  Y qw z|j| d }td||f  W q ty;   td|  Y qw tS )z4display refcounts for the objects with the given IDsrp  r   z4object %s has %d referrers [info from chunks cache].z-object %s not found [info from chunks cache].)rZ  r   r  r   r  r  r)   )	r   r   r   r   r   r   rj  rK  Zrefcountr   r   r   do_debug_refcount_obj  s   
zArchiver.do_debug_refcount_objc                 C   s   |j s
||  z?t|j|j|jdd |j D d}t	|j
d}tj||dd W d   n1 s7w   Y  W |  tS W |  tS |  w )zdump repository hintsc                 S   s   i | ]\}}t | |qS r   )r   decode)r   kvr   r   r   
<dictcomp>  s    z0Archiver.do_debug_dump_hints.<locals>.<dictcomp>)segmentsr  storage_quota_useshadow_indexr  r;  r<  N)Z_active_txnZprepare_txnZget_transaction_iddictrx  r  ry  rz  r7  rh   r   r   rF  Zrollbackr)   )r   r   r   hintsrp  r   r   r   do_debug_dump_hints  s$   
zArchiver.do_debug_dump_hintsc              	   C   s   ddl }|j2 |j |tj|jddd|j W d   n1 s$w   Y  W d   tS W d   tS 1 s<w   Y  tS )z&convert Borg profile to Python profiler   NF)rA  raw)marshalr$  inputrF  rm   unpackr)   )r   r   r  r   r   r   do_debug_convert_profile	  s   (z!Archiver.do_debug_convert_profile)r   r   c                 C   s   |   t | | jS )zCBreak the repository lock (e.g. in case it was left by a dead borg.)Z
break_lockr   r   )r   r   r   r   r   r   do_break_lock	  s   
zArchiver.do_break_locka0  
        The path/filenames used as input for the pattern matching start from the
        currently active recursion root. You usually give the recursion root(s)
        when invoking borg and these can be either relative or absolute paths.

        Starting with Borg 1.2, paths that are matched against patterns always
        appear relative. If you give ``/absolute/`` as root, the paths going
        into the matcher will start with ``absolute/``.
        If you give ``../../relative`` as root, the paths will be normalized
        as ``relative/``.

        A directory exclusion pattern can end either with or without a slash ('/').
        If it ends with a slash, such as `some/path/`, the directory will be
        included but not its content. If it does not end with a slash, such as
        `some/path`, both the directory and content will be excluded.

        Borg supports different pattern styles. To define a non-default
        style for a specific pattern, prefix it with two characters followed
        by a colon ':' (i.e. ``fm:path/*``, ``sh:path/**``).

        `Fnmatch <https://docs.python.org/3/library/fnmatch.html>`_, selector `fm:`
            This is the default style for ``--exclude`` and ``--exclude-from``.
            These patterns use a variant of shell pattern syntax, with '\*' matching
            any number of characters, '?' matching any single character, '[...]'
            matching any single character specified, including ranges, and '[!...]'
            matching any character not specified. For the purpose of these patterns,
            the path separator (backslash for Windows and '/' on other systems) is not
            treated specially. Wrap meta-characters in brackets for a literal
            match (i.e. `[?]` to match the literal character `?`). For a path
            to match a pattern, the full path must match, or it must match
            from the start of the full path to just before a path separator. Except
            for the root path, paths will never end in the path separator when
            matching is attempted.  Thus, if a given pattern ends in a path
            separator, a '\*' is appended before matching is attempted. A leading
            path separator is always removed.

        Shell-style patterns, selector `sh:`
            This is the default style for ``--pattern`` and ``--patterns-from``.
            Like fnmatch patterns these are similar to shell patterns. The difference
            is that the pattern may include `**/` for matching zero or more directory
            levels, `*` for matching zero or more arbitrary characters with the
            exception of any path separator. A leading path separator is always removed.

        Regular expressions, selector `re:`
            Regular expressions similar to those found in Perl are supported. Unlike
            shell patterns regular expressions are not required to match the full
            path and any substring match is sufficient. It is strongly recommended to
            anchor patterns to the start ('^'), to the end ('$') or both. Path
            separators (backslash for Windows and '/' on other systems) in paths are
            always normalized to a forward slash ('/') before applying a pattern. The
            regular expression syntax is described in the `Python documentation for
            the re module <https://docs.python.org/3/library/re.html>`_.

        Path prefix, selector `pp:`
            This pattern style is useful to match whole sub-directories. The pattern
            `pp:root/somedir` matches `root/somedir` and everything therein. A leading
            path separator is always removed.

        Path full-match, selector `pf:`
            This pattern style is (only) useful to match full paths.
            This is kind of a pseudo pattern as it can not have any variable or
            unspecified parts - the full path must be given. `pf:root/file.ext` matches
            `root/file.ext` only. A leading path separator is always removed.

            Implementation note: this is implemented via very time-efficient O(1)
            hashtable lookups (this means you can have huge amounts of such patterns
            without impacting performance much).
            Due to that, this kind of pattern does not respect any context or order.
            If you use such a pattern to include a file, it will always be included
            (if the directory recursion encounters it).
            Other include/exclude patterns that would normally match will be ignored.
            Same logic applies for exclude.

        .. note::

            `re:`, `sh:` and `fm:` patterns are all implemented on top of the Python SRE
            engine. It is very easy to formulate patterns for each of these types which
            requires an inordinate amount of time to match paths. If untrusted users
            are able to supply patterns, ensure they cannot supply `re:` patterns.
            Further, ensure that `sh:` and `fm:` patterns only contain a handful of
            wildcards at most.

        Exclusions can be passed via the command line option ``--exclude``. When used
        from within a shell, the patterns should be quoted to protect them from
        expansion.

        The ``--exclude-from`` option permits loading exclusion patterns from a text
        file with one pattern per line. Lines empty or starting with the number sign
        ('#') after removing whitespace on both ends are ignored. The optional style
        selector prefix is also supported for patterns loaded from a file. Due to
        whitespace removal, paths with whitespace at the beginning or end can only be
        excluded using regular expressions.

        To test your exclusion patterns without performing an actual backup you can
        run ``borg create --list --dry-run ...``.

        Examples::

            # Exclude '/home/user/file.o' but not '/home/user/file.odt':
            $ borg create -e '*.o' backup /

            # Exclude '/home/user/junk' and '/home/user/subdir/junk' but
            # not '/home/user/importantjunk' or '/etc/junk':
            $ borg create -e 'home/*/junk' backup /

            # Exclude the contents of '/home/user/cache' but not the directory itself:
            $ borg create -e home/user/cache/ backup /

            # The file '/home/user/cache/important' is *not* backed up:
            $ borg create -e home/user/cache/ backup / /home/user/cache/important

            # The contents of directories in '/home' are not backed up when their name
            # ends in '.tmp'
            $ borg create --exclude 're:^home/[^/]+\.tmp/' backup /

            # Load exclusions from file
            $ cat >exclude.txt <<EOF
            # Comment line
            home/*/junk
            *.tmp
            fm:aa:something/*
            re:^home/[^/]+\.tmp/
            sh:home/*/.thumbnails
            # Example with spaces, no need to escape as it is processed by borg
            some file with spaces.txt
            EOF
            $ borg create --exclude-from exclude.txt backup /

        A more general and easier to use way to define filename matching patterns
        exists with the ``--pattern`` and ``--patterns-from`` options. Using
        these, you may specify the backup roots, default pattern styles and
        patterns for inclusion and exclusion.

        Root path prefix ``R``
            A recursion root path starts with the prefix ``R``, followed by a path
            (a plain path, not a file pattern). Use this prefix to have the root
            paths in the patterns file rather than as command line arguments.

        Pattern style prefix ``P``
            To change the default pattern style, use the ``P`` prefix, followed by
            the pattern style abbreviation (``fm``, ``pf``, ``pp``, ``re``, ``sh``).
            All patterns following this line will use this style until another style
            is specified.

        Exclude pattern prefix ``-``
            Use the prefix ``-``, followed by a pattern, to define an exclusion.
            This has the same effect as the ``--exclude`` option.

        Exclude no-recurse pattern prefix ``!``
            Use the prefix ``!``, followed by a pattern, to define an exclusion
            that does not recurse into subdirectories. This saves time, but
            prevents include patterns to match any files in subdirectories.

        Include pattern prefix ``+``
            Use the prefix ``+``, followed by a pattern, to define inclusions.
            This is useful to include paths that are covered in an exclude
            pattern and would otherwise not be backed up.

        .. note::

            Via ``--pattern`` or ``--patterns-from`` you can define BOTH inclusion and exclusion
            of files using pattern prefixes ``+`` and ``-``. With ``--exclude`` and
            ``--exclude-from`` ONLY excludes are defined.

        The first matching pattern is used, so if an include pattern matches
        before an exclude pattern, the file is backed up. Note that a no-recurse
        exclude stops examination of subdirectories so that potential includes
        will not match - use normal excludes for such use cases.

        Example::

            # Define the recursion root
            R /
            # Exclude all iso files in any directory
            - **/*.iso
            # Explicitly include all inside etc and root
            + etc/**
            + root/**
            # Exclude a specific directory under each user's home directories
            - home/*/.cache
            # Explicitly include everything in /home
            + home/**
            # Explicitly exclude some directories without recursing into them
            ! re:^(dev|proc|run|sys|tmp)
            # Exclude all other files and directories
            # that are not specifically included earlier.
            - **

        .. note::

            It's possible that a sub-directory/file is matched while parent directories are not.
            In that case, parent directories are not backed up thus their user, group, permission,
            etc. can not be restored.

        Note that the default pattern style for ``--pattern`` and ``--patterns-from`` is
        shell style (`sh:`), so those patterns behave similar to rsync include/exclude
        patterns. The pattern style can be set via the `P` prefix.

        Patterns (``--pattern``) and excludes (``--exclude``) from the command line are
        considered first (in the order of appearance). Then patterns from ``--patterns-from``
        are added. Exclusion patterns from ``--exclude-from`` files are appended last.

        Examples::

            # backup pics, but not the ones from 2018, except the good ones:
            # note: using = is essential to avoid cmdline argument parsing issues.
            borg create --pattern=+pics/2018/good --pattern=-pics/2018 repo::arch pics

            # use a file with patterns:
            borg create --patterns-from patterns.lst repo::arch

        The patterns.lst file could look like that::

            # "sh:" pattern style is the default, so the following line is not needed:
            P sh
            R /
            # can be rebuild
            - home/*/.cache
            # they're downloads for a reason
            - home/*/Downloads
            # susan is a nice person
            # include susans home
            + home/susan
            # also back up this exact file
            + pf:home/bobby/specialfile.txt
            # don't backup the other home directories
            - home/*
            # don't even look in /proc
            ! proc

        You can specify recursion roots either on the command line or in a patternfile::

            # these two commands do the same thing
            borg create --exclude home/bobby/junk repo::arch /home/bobby /home/susan
            borg create --patterns-from patternfile.lst repo::arch

        The patternfile::

            # note that excludes use fm: by default and patternfiles use sh: by default.
            # therefore, we need to specify fm: to have the same exact behavior.
            P fm
            R /home/bobby
            R /home/susan

            - home/bobby/junk

        This allows you to share the same patterns between multiple repositories
        without needing to specify them on the command line.

r  a=	  
        Repository (or Archive) URLs, ``--prefix``, ``--glob-archives``, ``--comment``
        and ``--remote-path`` values support these placeholders:

        {hostname}
            The (short) hostname of the machine.

        {fqdn}
            The full name of the machine.

        {reverse-fqdn}
            The full name of the machine in reverse domain name notation.

        {now}
            The current local date and time, by default in ISO-8601 format.
            You can also supply your own `format string <https://docs.python.org/3.8/library/datetime.html#strftime-and-strptime-behavior>`_, e.g. {now:%Y-%m-%d_%H:%M:%S}

        {utcnow}
            The current UTC date and time, by default in ISO-8601 format.
            You can also supply your own `format string <https://docs.python.org/3.8/library/datetime.html#strftime-and-strptime-behavior>`_, e.g. {utcnow:%Y-%m-%d_%H:%M:%S}

        {user}
            The user name (or UID, if no name is available) of the user running borg.

        {pid}
            The current process ID.

        {borgversion}
            The version of borg, e.g.: 1.0.8rc1

        {borgmajor}
            The version of borg, only the major version, e.g.: 1

        {borgminor}
            The version of borg, only major and minor version, e.g.: 1.0

        {borgpatch}
            The version of borg, only major, minor and patch version, e.g.: 1.0.8

        If literal curly braces need to be used, double them for escaping::

            borg create /path/to/repo::{{literal_text}}

        Examples::

            borg create /path/to/repo::{hostname}-{user}-{utcnow} ...
            borg create /path/to/repo::{hostname}-{now:%Y-%m-%d_%H:%M:%S} ...
            borg prune --glob-archives '{hostname}-*' ...

        .. note::
            systemd uses a difficult, non-standard syntax for command lines in unit files (refer to
            the `systemd.unit(5)` manual page).

            When invoking borg from unit files, pay particular attention to escaping,
            especially when using the now/utcnow placeholders, since systemd performs its own
            %-based variable replacement even in quoted text. To avoid interference from systemd,
            double all percent signs (``{hostname}-{now:%Y-%m-%d_%H:%M:%S}``
            becomes ``{hostname}-{now:%%Y-%%m-%%d_%%H:%%M:%%S}``).

placeholdersa  
        It is no problem to mix different compression methods in one repo,
        deduplication is done on the source data chunks (not on the compressed
        or encrypted data).

        If some specific chunk was once compressed and stored into the repo, creating
        another backup that also uses this chunk will not change the stored chunk.
        So if you use different compression specs for the backups, whichever stores a
        chunk first determines its compression. See also borg recreate.

        Compression is lz4 by default. If you want something else, you have to specify what you want.

        Valid compression specifiers are:

        none
            Do not compress.

        lz4
            Use lz4 compression. Very high speed, very low compression. (default)

        zstd[,L]
            Use zstd ("zstandard") compression, a modern wide-range algorithm.
            If you do not explicitly give the compression level L (ranging from 1
            to 22), it will use level 3.
            Archives compressed with zstd are not compatible with borg < 1.1.4.

        zlib[,L]
            Use zlib ("gz") compression. Medium speed, medium compression.
            If you do not explicitly give the compression level L (ranging from 0
            to 9), it will use level 6.
            Giving level 0 (means "no compression", but still has zlib protocol
            overhead) is usually pointless, you better use "none" compression.

        lzma[,L]
            Use lzma ("xz") compression. Low speed, high compression.
            If you do not explicitly give the compression level L (ranging from 0
            to 9), it will use level 6.
            Giving levels above 6 is pointless and counterproductive because it does
            not compress better due to the buffer size used by borg - but it wastes
            lots of CPU cycles and RAM.

        auto,C[,L]
            Use a built-in heuristic to decide per chunk whether to compress or not.
            The heuristic tries with lz4 whether the data is compressible.
            For incompressible data, it will not use compression (uses "none").
            For compressible data, it uses the given C[,L] compression - with C[,L]
            being any valid compression specifier.

        obfuscate,SPEC,C[,L]
            Use compressed-size obfuscation to make fingerprinting attacks based on
            the observable stored chunk size more difficult. Note:

            - You must combine this with encryption, or it won't make any sense.
            - Your repo size will be bigger, of course.
            - A chunk is limited by the constant ``MAX_DATA_SIZE`` (cur. ~20MiB).

            The SPEC value determines how the size obfuscation works:

            *Relative random reciprocal size variation* (multiplicative)

            Size will increase by a factor, relative to the compressed data size.
            Smaller factors are used often, larger factors rarely.

            Available factors::

              1:     0.01 ..        100
              2:     0.1  ..      1,000
              3:     1    ..     10,000
              4:    10    ..    100,000
              5:   100    ..  1,000,000
              6: 1,000    .. 10,000,000

            Example probabilities for SPEC ``1``::

              90   %  0.01 ..   0.1
               9   %  0.1  ..   1
               0.9 %  1    ..  10
               0.09% 10    .. 100

            *Randomly sized padding up to the given size* (additive)

            ::

              110: 1kiB (2 ^ (SPEC - 100))
              ...
              120: 1MiB
              ...
              123: 8MiB (max.)

        Examples::

            borg create --compression lz4 REPO::ARCHIVE data
            borg create --compression zstd REPO::ARCHIVE data
            borg create --compression zstd,10 REPO::ARCHIVE data
            borg create --compression zlib REPO::ARCHIVE data
            borg create --compression zlib,1 REPO::ARCHIVE data
            borg create --compression auto,lzma,6 REPO::ARCHIVE data
            borg create --compression auto,lzma ...
            borg create --compression obfuscate,110,none ...
            borg create --compression obfuscate,3,auto,zstd,10 ...
            borg create --compression obfuscate,2,zstd,6 ...

r   c                 C   s  |j s
|  | jS |j | jv rtt| j|j   | jS |j |v rM|jr0t||j  j | jS |jrCd ||j  _||j    | jS ||j    | jS g }|d|j  g7 }|dg7 }|ddt	|
  g7 }|ddt	| j
  g7 }|d| | jS )NzNo help available on %s.zTry one of the following:z    Commands: %s, z    Topics: %sr  )topic
print_helphelptextr   rt   epilog_onlyepilog
usage_onlyra  rz  r  r   r   )r   r   commandsr   	msg_linesr   r   r   do_help
  s.   


zArchiver.do_helpc                 C   s   |   tS )zdisplay infos about subcommand)r  r)   )r   r   r   r   r   r   do_subcommand_help
  s   zArchiver.do_subcommand_helpc                 C   sf   g d}t |d d  D ]$\}}|D ]\}}}||r/|d ur(|||||< t|tjd qq|S )N))	--noatimeNzGWarning: "--noatime" has been deprecated because it is the default now.)--nobsdflagsNzCWarning: "--nobsdflags" has been deprecated. Use --noflags instead.)--numeric-ownerNzJWarning: "--numeric-owner" has been deprecated. Use --numeric-ids instead.)--remote-ratelimitNzRWarning: "--remote-ratelimit" has been deprecated. Use --upload-ratelimit instead.)--remote-bufferNzLWarning: "--remote-buffer" has been deprecated. Use --upload-buffer instead.)--prefixNzZWarning: "--prefix" has been deprecated. Use "--glob-archives 'yourprefix*'" (-a) instead.r   )r  r"  replacer   r  r  )r   r   Zdeprecationsrm  r  Zold_namenew_namer   r   r   r   preprocess_args
  s   	
zArchiver.preprocess_argsc                   @   s2   e Zd ZdZdd ZdddZdejfdd	Zd
S )zArchiver.CommonOptionsa  
        Support class to allow specifying common options directly after the top-level command.

        Normally options can only be specified on the parser defining them, which means
        that generally speaking *all* options go after all sub-commands. This is annoying
        for common options in scripts, e.g. --remote-path or logging options.

        This class allows adding the same set of options to both the top-level parser
        and the final sub-command parsers (but not intermediary sub-commands, at least for now).

        It does so by giving every option's target name ("dest") a suffix indicating its level
        -- no two options in the parser hierarchy can have the same target --
        then, after parsing the command line, multiple definitions are resolved.

        Defaults are handled by only setting them on the top-level parser and setting
        a sentinel object in all sub-parsers, which then allows one to discern which parser
        supplied the option.
        c                 C   s(   || _ || _t | _t | _t | _dS )a  
            *define_common_options* should be a callable taking one argument, which
            will be a argparse.Parser.add_argument-like function.

            *define_common_options* will be called multiple times, and should call
            the passed function to define common options exactly the same way each time.

            *suffix_precedence* should be a tuple of the suffixes that will be used.
            It is ordered from lowest precedence to highest precedence:
            An option specified on the parser belonging to index 0 is overridden if the
            same option is specified on any parser with a higher index.
            N)define_common_optionssuffix_precedencer{  common_optionsr  append_optionsobjectdefault_sentinel)r   r  r  r   r   r   r   
  s
   zArchiver.CommonOptions.__init__Fc                    s8   j v sJ  fdd}|d | dS )a  
            Add common options to *parser*.

            *provide_defaults* must only be True exactly once in a parser hierarchy,
            at the top level, and False on all lower levels. The default is chosen
            accordingly.

            *suffix* indicates the suffix to use internally. It also indicates
            which precedence the *parser* has for common options. See *suffix_precedence*
            of __init__.
            c                     s   d|v rS| dd |d dv sJ |d dk}|r-j|d  |d g ks,J dnj t |d  |d  7  < sS|d | |d< |sSj|d<  j| i | d S )	Nr   actionstore)helpstore_const
store_truestore_falser  r)  r)  r   zCThe default is explicitly constructed as an empty list in resolve()r  )
setdefaultr  r  r  r  r  add_argument)r   r   Z	is_appendZcommon_groupprovide_defaultsr   suffixr   r   r    s   
z=Archiver.CommonOptions.add_common_group.<locals>.add_argumentzCommon optionsN)r  add_argument_groupr  )r   r   r  r  r  r   r  r   add_common_group  s   
z'Archiver.CommonOptions.add_common_groupr   c           
   
   C   s   | j D ]4}| j|g D ]*}|| }|}t||| j}|| jur&t||| zt|| W q ty6   Y qw q| jD ]'}g }| j D ]}|| }||v r[t||}	t|| |	|	 qBt||| q;dS )zd
            Resolve the multiple definitions of each common option to the final value.
            N)
r  r  r   r   r  r   delattrAttributeErrorr  extend)
r   r   r  r   Zmap_fromZmap_tor"  Zoption_valueZextend_fromr   r   r   r   resolve0  s0   






zArchiver.CommonOptions.resolveN)F)	r   r   r   r   r   r  r   Z	Namespacer  r   r   r   r   CommonOptions
  s
    
(r  c           9   
      sB  ddddddddfd	d
}dd }dddddfddddddd  fdd}t jjddd}|jtj|g g d j|dd|_|j	ddd d!t
 d"d# |jj|d$dd% t jdjd&}|jg g d' |j|d( t jdjd&}|jg g d' |j|d) |d*}|jd+krjj|_||_t j|_d,|_|| |S |jd-d.d/}|d0}	|jd1|gdd2|	t jd2d3}
|
jd-d.d/}|
jtj|
d4 |d5}|jd6|gdjj|t jd7d3}
|
jjd8 |
j	d9d:tdd;d<d= |
j	d>d?d@dA |dB}|jdC|gdjj|t jdDd3}
|
jjd8 |
j	d9d:dEdFtdd;dGdH |dI}|jdJ|gdjj|t jdKd3}
|
jjd8 |
j	d9dLdEdFt dMdH |
j	dNdOdPdQdR |
j	dSdTdPdUdR |
j	dVdWdPdXdR |
j	dYdZdPd[dR |
j	d\d]dPd^dR |
j	d_d`datdbdcdd  |
 |de}|jdf|gdjj|t jdgd3}
|
jjd8 |
j	d9d:dEdFtdd;dhdH |
j	didjdPdkdR |
j	dldmdntdodpdd |dq}|jdr|gdjj|t jdsd3}
|
jjd8 |
j	dtdudvdPdwdR |
 }|j	dxdydzdPd{dR |j	d|d}d~dPddR |
j	d9d:dEdFtdddddH |
j	dddEdd |
j	dddEdd |d}|jd|gdjj|t jdd3}
|
jjd8 |
j	ddddPddR |
j	ddddPddR |
j	d}ddPddR |
j	dddtdd |
j	ddPdd |
j	dddPddR |
j	dddddd |
j	dddt dbdd |
j	dddt!dbdd |
j	ddddd t"ddd |
j	ddPdd |
j	ddPdd |
j	ddPdd |
j	ddddA |
dd}|j	dddPddR |
#d¡}|j	ddddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddPddR |j	dddtt$t%dt% d |j	dddPddR |
#d}|j	dddt&dFdd |j	dddt'd ddd |j	dtdd`dtdddd |j	dddt(t)td t) d |j	ddddt*t*dddd |
j	d9dtdd;d	d= |
j	d
d?dt+ddd |d}|jd|gdd|t jdd3}
|
jd-d.d/}|
jtj|
d4 |d}|jd|gdj,j|t jdd3}
|
jj,d8 |d}|jd|gdj-j|t jdd3}
|
jj-d8 |
j	d9dtdd;dd= |d}|jd|gdj.j|t jdd3}
|
jj.d8 |
j	d9dtdd;dd= |
j	d>d?t+dd= |d}|jd|gdj/j|t jdd3}
|
jj/d8 |
j	d9d:tdd;d d= |
j	d>d?t+dd= |d!}|jd"|gdj0j|t jd#d3}
|
jj0d8 |
j	d9d:tdd;d d= |
j	d$d%dPd&dR |
j	d'd(d)d t1d*d+ |
j	d,d-d.d t1d/d+ |d0}|jd1|gdj2j|t jd2d3}
|
jj2d8 |
j	d9d:tdd;d3d= |
j	d4d5t+d6d= |d7}|jd8|gdj3j|t jd9d3}
|
jj3d8 |
j	d9d:tdd;d:d= |
j	d>d?t+d;d= |d<}|jd=|gdj4j|t jd>d3}
|
jj4d8 |
j	d9d:tdd;d:d= |
j	d?d@t+dAd= |
j	d>d?t+dBd= |dC} |jdD|gdj5j| t jdEd3}
|
jj5d8 |
j	d9d:tdd;d:d= |
j	d?d@t+dFd= |
j	d>d?t+dGd= |dH}!|jdI|gdj6j|!t jdJd3}
|
jj6d8 |
j	d9d:tdd;d:d= |
j	dKdLdMt+dNdO |dP}"|jdQ|gdj7j|"t jdRd3}
|
jj7d8 |
j	d9d:tdd;d:d= |
j	dKdLdMt+dSdO |dT}#|jdU|gdj8j|#t jdVd3}
|
jj8d8 |
j	d9d:tdd;d d= |
j	d>d?t+dd= |dW}$|jdX|gdj9j|$t jdYd3}
|
jj9d8 |
j	dZd[t :d\d]d= |
j	d^d_t :d`dad= |db}%|jdz|gdj;j|%t jdcd3}
|
jj;d8 |
j	ddddPdddR |
j	d}ddPdedR |
j	ddddPdfdR |
j	dgdhdPdidR |
j	djdkdldbdmdn |
j	dodpdPdqdR |
j	d\d]dPd^dR |
j	dtdd`dtdddd |
j	d9dLdEdFt drdH |
j	dsdddtd  |
 |du}&|jdv|gdj<j|&t jdwd3}
|
jj<d8 |
j	dddPddR |
j	dddPdxdR |
j	dydzdPd{dR |
j	d|d}dPd~dR |
j	ddPdd |
j	ddPdd |
j	d9dtdd;dd= |
j	ddt= dd= |
j	d
d?dt+ddO |
 |d}'|jd|gdj>j|'t jdd3}
|
jj>d8 |
j	ddddd |
j	d}ddPddR |
j	d9dtdd;dd= |
j	ddddA |
j	d
d?dt+ddO |
dd |d}(|jd|gdj?j|(t jdd3}
|
jj?d8 |
j	d}ddPddR |
j	ddddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	dddPddR |
j	d9dtdd;dd= |
j	d
d?dt+ddO |
dd |jd|gddd}
|
j	dddPd |
j	dddPd |
jtj@||jAd8 |
j	ddt+dEdd |d})|jd|gdjBj|)t jdd3}
|
jjBd8 |
j	d9dLdEdFt ddH |
j	ddPdd  |
 |d}*|jd|gdjCj|*t jdd3}
|
jjCd8 |
j	d9d:dEdFtdd;ddH |
j	dddddtD dd |
j	dddPddR |
j	dddd tEdÐd+ |
j	dĐddPddR |jd|gdddFt jdd3}
|
jd-d.d/}+|
jtj|
d4 |dʃ},|+jd|gdjFj|,t jdd3}
|
jjFd8 |
j	d9d:dEdFtdd;d͍ |
j	d>d?dEt+dΐdO |
j	dϐddPddR |
j	dҐddPddR |dՃ}-|+jd|gdjGj|-t jdd3}
|
jjGd8 |
j	d9d:dEdFtdd;d͍ |
j	d>d?dEt+dؐdO |
j	dϐddPddR |dڃ}.|+jd|gdjHj|.t jdd3}
|
jjHd8 |
j	d9d:dEdFtdd;d͍ |d݃}/|+jd|gdjIj|/t jdd3}
|
jjId8 |
j	d9d:dEdFtdd;d͍ |dtJK  tLMd tNK  tLMd tOK  }0|jd~|gdjPj|0t jdd3}
|
jjPd8 |
j	ddPddd |
j	dddPddR |
j	ddddd |
j	ddPdd |
j	ddPdd |
j	d9dLdEdFt ddH |
j	d
d?dt+ddO  |
 |
 |jd|gdjj|t jd,d3}
||
 |d}1|jd|gdjQj|1t jdd3}
|
jjQd8 |
j	ddddPdddR |
j	djdkdPddR |
j	ddddPdfdR |
j	d}ddPddR |
j	dddtRdd |
j	dd dtdbdd |
j	ddtdbdd |
j	ddd	tdbd
d |
j	dxddtdbdd |
j	dddtdbdd |
j	dddtdbdd |
j	dddtdbdd  |
ddd |
j	d\d]dPd^dR |
j	dtdd`dtdddd |
j	d9d:dEdFtdd;ddH |d}2|jd|gdjSj|2t jjSjd3}
|
jjSd8 |
j	d}ddPddR |
j	dddtdd |
j	ddddPddR |
j	ddddPddR |
dd |
#d}|j	d d!d"d t= d#d$ |j	dtddtdd`dd% |j	dddt&d dd |j	dddt'd d&dd |j	ddddt*t*dddd |j	d'dd(dEd)d*d+d,d- |j	dddtt(d d.d |
j	d9dLdEdFt d/dH |
j	d
d?dt+d0dO |d1}3|jd2|gdjTj|3t jd3d3}
|
jjTd8 |
j	d9dtdd;d4d= |
j	dd5t= d6d= |d7}4|jd8|gdjUj|4t jd9d3}
|
jjUd8 |
j	d:d?d;d<d=d |
j	d>d?d?d<d@d |
j	dddPdAdR |
j	dddtEd dBdd |dC}5|jdD|gdjVj|5t jdEd3}
|
jjVd8 |
j	dFdGt+dHd= |dI}6|jdJ|gdjWj|6t jdKd3}
|
jjWd8 |
j	ddddPdddR |
j	dLdMdPdNdR |
j	djdOdPdPdR |
j	dQdRdPdSdR |
j	dTdUdPdVdR |
j	dWdXdPdYdR |
j	d9d:dEdFtdd;dZdH |d[}7|jd\|gdjXj|7t jd]d3}
|
jjXd8 |
j	d9d:tdd;d^d= |
j	d_d`dadA |
j	dbdct jYddd |de}8|jdf|gdjZj|8t jjZjd3}
|
jjZd8 |
j	dddtddg |
j	ddddPdddn |
j	d}ddPdddn |
j	dddtdhdi |
j	ddPdjd |
j	dkdldPddmdn |
#d}|j	ddddFddn |j	ddt'd dd&d% |j	dtddtdd`dd% |j	ddtt(t)dd t) do |j	ddddt*t*dddd |
j	d9dtdd;d	d= |
j	ddpdqdA |S (r  Nu;   "I am seeing ‘A’ (added) status for a unchanged file!?"z"Separate compaction"z"Item flags"z"borg help patterns"z"borg help placeholders"z:Internals -> Data structures and file formats -> Key fileszborg key export --help)Za_status_oddityZseparate_compactionZlist_item_flagsZborg_patternsZborg_placeholdersZ	key_filesZborg_key_exportc                    sf   t |  } ztj}W n ty   d}Y nw |dv r#dd | D } d| } |dkr1t|  } | S )Ncommand-line)r  build_usagec                 S   s   g | ]	}| d s|qS )z.. man)r"  )r   liner   r   r   rB  n  r  zAArchiver.build_parser.<locals>.process_epilog.<locals>.<listcomp>r  )r  r  
splitlinesborgdoc_moder  ra  rt   )r  r  )rst_plain_text_referencesr   r   process_epilogg  s   


z-Archiver.build_parser.<locals>.process_epilogc              
   S   s  | ddddd | dddd	d
dd | ddddd
dd | dddd
d
dd | ddddddd
dd | ddddd
dd | ddddg dd | d d!d"d#d$d% | d&d'd#d(d% | d)d*d#d+d% | d,d-d.t d/d0d1 | d2d3d4tjd5d6 | d7d8d#d9d% | d:d;d#d<d% | d=d>d?d@dA tdBd1 | dCdDdEdFdG | dHdIdJt dKdL | dMdIdJt dNdL | dOdPdQt dRdL | dSdPdQt dTdL | dUdVd#dWd% | dXdYdZd d[d\ | d]d^d_d`dG d S )aN-hz--helpr  zshow this help message and exitr  r  z
--critical	log_levelr  criticalr   zwork on log level CRITICAL)r   r  constr   r  z--errorr   zwork on log level ERRORz	--warningz#work on log level WARNING (default)z--infoz-vz	--verboser  zwork on log level INFOz--debugr  z,enable debug output, work on log level DEBUGz--debug-topicTOPICdebug_topicsr)  zenable TOPIC debugging (can be specified multiple times). The logger path is borg.debug.<TOPIC> if TOPIC is not fully qualified.)metavarr   r  r   r  z-pz
--progressr   r  zshow progress informationr   r  r  z--iecr   z%format using IEC units (1KiB = 1024B)z
--log-jsonr   z>Output one JSON object per log line instead of formatted text.z--lock-waitSECONDSr   r   zRwait at most SECONDS for acquiring a repository/cache lock (default: %(default)d).r  r   r   r   r  z--bypass-lockr   r  zBypass locking mechanismr   r  r   r  z--show-versionshow_versionzshow/log the borg versionz	--show-rcshow_rczshow/log the return code (rc)z--umaskMumaskc                 S   
   t | dS N   r  r  r   r   r   rD       
 zFArchiver.build_parser.<locals>.define_common_options.<locals>.<lambda>z3set umask to M (local only, default: %(default)04o)z--remote-pathPATHZremote_pathz;use PATH as borg executable on the remote (default: "borg")r  r   r  r  ZRATEZupload_ratelimitz.deprecated, use ``--upload-ratelimit`` insteadr  r   r   r  z--upload-ratelimitz@set network upload rate limit in kiByte/s (default: 0=unlimited)r  ZUPLOAD_BUFFERZupload_bufferz+deprecated, use ``--upload-buffer`` insteadz--upload-bufferz=set network upload buffer size in MiB. (default: 0=no buffer)z--consider-part-filesr   z>treat part files like normal files (e.g. to list/extract them)z--debug-profileFILEdebug_profilezWrite execution profile in Borg format into FILE. For local use a Python-compatible file can be generated by suffixing FILE with ".pyprof".r  r   r   r  z--rshZRSHZrshzHUse this command to connect to the 'borg serve' process (default: 'ssh'))r  r   ZSUPPRESSZUMASK_DEFAULT)Zadd_common_optionr   r   r   r  t  s   







z4Archiver.build_parser.<locals>.define_common_optionsF)	tag_filesr  c             	   S   s   | ddddt ddd | dd	td
d | ddtdd | ddtdd |r?| ddddd | ddddtdd | ddddd |rM| ddd td!d"d# d S d S )$N-ez	--excludeZPATTERNr  r)  zexclude paths matching PATTERNr  r   r   r  r  z--exclude-fromZEXCLUDEFILEz4read exclude patterns from EXCLUDEFILE, one per line)r  r  r  z	--patternz&include/exclude paths matching PATTERNz--patterns-fromZPATTERNFILEz<read include/exclude patterns from PATTERNFILE, one per linez--exclude-cachesr  r  z_exclude directories that contain a CACHEDIR.TAG file (http://www.bford.info/cachedir/spec.html)r  z--exclude-if-presentr  r  zYexclude directories that are tagged by containing a filesystem object with the given NAME)r  r   r  r   r  z--keep-exclude-tagsr  zyif tag objects are specified with ``--exclude-if-present``, don't omit the tag objects themselves from the backup archivez--strip-componentsNUMBERr  r   ziRemove the specified number of leading path elements. Paths with fewer elements will be silently skipped.r  )rx   rv   ru   rw   r   r  )
add_optionr  r  r   r   r   define_exclude_and_patterns  s<   

z:Archiver.build_parser.<locals>.define_exclude_and_patternsc                    s    |  d} |jfi | |S )NzInclude/Exclude options)r  r  )	subparserr   exclude_group)r  r   r   define_exclusion_group  s   
z5Archiver.build_parser.<locals>.define_exclusion_groupT)r-  
first_lastc                S   s   |  dd}| }|jddddttdd |jd	d
ddttdd |r8d}|jdddt|ddt	|d |rV| }|jddddt
dd |jddddt
dd d S d S )NzArchive filtersz5Archive filters can be applied to repository targets.z-Pr  PREFIXr1  zConly consider archive names starting with this prefix. (deprecated)r  z-az--glob-archivesZGLOBr2  zonly consider archive names matching the glob. sh: rules apply (without actually using the sh: prefix), see "borg help patterns".rJ   z	--sort-byZKEYSr-  zHComma-separated list of sorting keys; valid keys are: {}; default is: {}r  r  z--firstNr+  r   z:consider first N archives after other filters were appliedr  r   r   r   r  z--lastr,  z9consider last N archives after other filters were applied)r  add_mutually_exclusive_groupr  r5   r   r6   r8   r@  ra  rO   r0   )r  r-  r  Zfilters_groupr  Zsort_by_defaultr   r   r   define_archive_filters_group  s6   

z;Archiver.build_parser.<locals>.define_archive_filters_groupc                    s   | j jd | jddt dd | jdddd	d
 | jddtdd | jdddddd | jddttdd | jddddd | jddddd  |  | jdddtdd  | d!d" d S )#Nr   r   REPOSITORY_OR_ARCHIVEzrepository or archive to mountr  r   r  --consider-checkpointsr  r  KShow checkpoint archives in the repository contents list (default: hidden).r  r   r  r  
MOUNTPOINTzwhere to mount filesystemz-fz--foregroundr  z$stay in foreground, do not daemonizer  z-or  zExtra mount options)r   r   r  r  r  r   )deprecated, use ``--numeric-ids`` instead--numeric-idsz6use numeric user and group identifiers from archive(s)r  r  r    (paths to extract; patterns are supportedr  nargsr   r  Tr  )set_defaultsr  r  r1   r   r   )r   )r  r  r   r   r   define_borg_mount  s8   




z0Archiver.build_parser.<locals>.define_borg_mountzBorg - Deduplicated Backups)r   descriptionadd_help)r   r  r  )_maincommand_midcommand_subcommand)r  z-Vz	--versionr&  z	%(prog)s zshow version number and exit)r  r&  r  r  )r  )r  r   )r  r  r  r  a  
        This command mounts an archive as a FUSE filesystem. This can be useful for
        browsing an archive or restoring individual files. Unless the ``--foreground``
        option is given the command will run in the background until the filesystem
        is ``umounted``.

        The command ``borgfs`` provides a wrapper for ``borg mount``. This can also be
        used in fstab entries:
        ``/path/to/repo /mnt/point fuse.borgfs defaults,noauto 0 0``

        To allow a regular user to use fstab entries, add the ``user`` option:
        ``/path/to/repo /mnt/point fuse.borgfs defaults,noauto,user 0 0``

        For FUSE configuration and mount options, see the mount.fuse(8) manual page.

        Borg's default behavior is to use the archived user and group names of each
        file and map them to the system's respective user and group ids.
        Alternatively, using ``numeric-ids`` will instead use the archived user and
        group ids without any mapping.

        The ``uid`` and ``gid`` mount options (implemented by Borg) can be used to
        override the user and group ids of all files (i.e., ``borg mount -o
        uid=1000,gid=1000``).

        The man page references ``user_id`` and ``group_id`` mount options
        (implemented by fuse) which specify the user and group id of the mount owner
        (aka, the user who does the mounting). It is set automatically by libfuse (or
        the filesystem if libfuse is not used). However, you should not specify these
        manually. Unlike the ``uid`` and ``gid`` mount options which affect all files,
        ``user_id`` and ``group_id`` affect the user and group id of the mounted
        (base) directory.

        Additional mount options supported by borg:

        - ``versions``: when used with a repository mount, this gives a merged, versioned
          view of the files in the archives. EXPERIMENTAL, layout may change in future.
        - ``allow_damaged_files``: by default damaged files (where missing chunks were
          replaced with runs of zeros by ``borg check --repair``) are not readable and
          return EIO (I/O error). Set this option to read such files.
        - ``ignore_permissions``: for security reasons the ``default_permissions`` mount
          option is internally enforced by borg. ``ignore_permissions`` can be given to
          not enforce ``default_permissions``.

        The BORG_MOUNT_DATA_CACHE_ENTRIES environment variable is meant for advanced users
        to tweak the performance. It sets the number of cached data chunks; additional
        memory usage can be up to ~8 MiB times this number. The default is the number
        of CPU cores.

        When the daemonized process receives a signal or crashes, it does not unmount.
        Unmounting in these cases could cause an active rsync or similar process
        to unintentionally delete data.

        When running in the foreground ^C/SIGINT unmounts cleanly, but other
        signals or crashes do not.
        borgfszmount repositoryzrequired argumentsz	<command>)titler  z%These commands do various benchmarks.	benchmarkzbenchmark command)parentsr  r  r  formatter_classr  )r   aV	  
        This command benchmarks borg CRUD (create, read, update, delete) operations.

        It creates input data below the given PATH and backups this data into the given REPO.
        The REPO must already exist (it could be a fresh empty repo or an existing repo, the
        command will create / read / update / delete some archives named borg-benchmark-crud\* there.

        Make sure you have free space there, you'll need about 1GB each (+ overhead).

        If your repository is encrypted and borg needs a passphrase to unlock the key, use::

            BORG_PASSPHRASE=mysecret borg benchmark crud REPO PATH

        Measurements are done with different input file sizes and counts.
        The file contents are very artificial (either all zero or all random),
        thus the measurement results do not necessarily reflect performance with real data.
        Also, due to the kind of content used, no compression is used in these benchmarks.

        C- == borg create (1st archive creation, no compression, do not use files cache)
              C-Z- == all-zero files. full dedup, this is primarily measuring reader/chunker/hasher.
              C-R- == random files. no dedup, measuring throughput through all processing stages.

        R- == borg extract (extract archive, dry-run, do everything, but do not write files to disk)
              R-Z- == all zero files. Measuring heavily duplicated files.
              R-R- == random files. No duplication here, measuring throughput through all processing
              stages, except writing to disk.

        U- == borg create (2nd archive creation of unchanged input files, measure files cache speed)
              The throughput value is kind of virtual here, it does not actually read the file.
              U-Z- == needs to check the 2 all-zero chunks' existence in the repo.
              U-R- == needs to check existence of a lot of different chunks in the repo.

        D- == borg delete archive (delete last remaining archive, measure deletion + compaction)
              D-Z- == few chunks to delete / few segments to compact/remove.
              D-R- == many chunks to delete / many segments to compact/remove.

        Please note that there might be quite some variance in these measurements.
        Try multiple measurements and having a otherwise idle machine (and network, if you use it).
        Zcrudz7benchmarks borg CRUD (create, extract, update, delete).r  r   Z
REPOSITORY)r   z,repository to use for benchmark (must exist)r  r   r  z(path were to create benchmark input data)r  r  z
        This command breaks the repository and cache locks.
        Please use carefully and only while no borg process (on any machine) is
        trying to access the Cache or the Repository.
        z
break-lockz break repository and cache locks?rF  z'repository for which to break the locks)r  r  r   r   r  a  
        The check command verifies the consistency of a repository and its archives.
        It consists of two major steps:

        1. Checking the consistency of the repository itself. This includes checking
           the segment magic headers, and both the metadata and data of all objects in
           the segments. The read data is checked by size and CRC. Bit rot and other
           types of accidental damage can be detected this way. Running the repository
           check can be split into multiple partial checks using ``--max-duration``.
           When checking a remote repository, please note that the checks run on the
           server and do not cause significant network traffic.

        2. Checking consistency and correctness of the archive metadata and optionally
           archive data (requires ``--verify-data``). This includes ensuring that the
           repository manifest exists, the archive metadata chunk is present, and that
           all chunks referencing files (items) in the archive exist. This requires
           reading archive and file metadata, but not data. To cryptographically verify
           the file (content) data integrity pass ``--verify-data``, but keep in mind
           that this requires reading all data and is hence very time consuming. When
           checking archives of a remote repository, archive checks run on the client
           machine because they require decrypting data and therefore the encryption
           key.

        Both steps can also be run independently. Pass ``--repository-only`` to run the
        repository checks only, or pass ``--archives-only`` to run the archive checks
        only.

        The ``--max-duration`` option can be used to split a long-running repository
        check into multiple partial checks. After the given number of seconds the check
        is interrupted. The next partial check will continue where the previous one
        stopped, until the full repository has been checked. Assuming a complete check
        would take 7 hours, then running a daily check with ``--max-duration=3600``
        (1 hour) would result in one full repository check per week. Doing a full
        repository check aborts any previous partial check; the next partial check will
        restart from the beginning. With partial repository checks you can run neither
        archive checks, nor enable repair mode. Consequently, if you want to use
        ``--max-duration`` you must also pass ``--repository-only``, and must not pass
        ``--archives-only``, nor ``--repair``.

        **Warning:** Please note that partial repository checks (i.e. running it with
        ``--max-duration``) can only perform non-cryptographic checksum checks on the
        segment files. A full repository check (i.e. without ``--max-duration``) can
        also do a repository index check. Enabling partial repository checks excepts
        archive checks for the same reason. Therefore partial checks may be useful with
        very large repositories only where a full check would take too long.

        The ``--verify-data`` option will perform a full integrity verification (as
        opposed to checking the CRC32 of the segment) of data, which means reading the
        data from the repository, decrypting and decompressing it. It is a complete
        cryptographic verification and hence very time consuming, but will detect any
        accidental and malicious corruption. Tamper-resistance is only guaranteed for
        encrypted repositories against attackers without access to the keys. You can
        not use ``--verify-data`` with ``--repository-only``.

        About repair mode
        +++++++++++++++++

        The check command is a readonly task by default. If any corruption is found,
        Borg will report the issue and proceed with checking. To actually repair the
        issues found, pass ``--repair``.

        .. note::

            ``--repair`` is a **POTENTIALLY DANGEROUS FEATURE** and might lead to data
            loss! This does not just include data that was previously lost anyway, but
            might include more data for kinds of corruption it is not capable of
            dealing with. **BE VERY CAREFUL!**

        Pursuant to the previous warning it is also highly recommended to test the
        reliability of the hardware running Borg with stress testing software. This
        especially includes storage and memory testers. Unreliable hardware might lead
        to additional data loss.

        It is highly recommended to create a backup of your repository before running
        in repair mode (i.e. running it with ``--repair``).

        Repair mode will attempt to fix any corruptions found. Fixing corruptions does
        not mean recovering lost data: Borg can not magically restore data lost due to
        e.g. a hardware failure. Repairing a repository means sacrificing some data
        for the sake of the repository as a whole and the remaining data. Hence it is,
        by definition, a potentially lossy task.

        In practice, repair mode hooks into both the repository and archive checks:

        1. When checking the repository's consistency, repair mode will try to recover
           as many objects from segments with integrity errors as possible, and ensure
           that the index is consistent with the data stored in the segments.

        2. When checking the consistency and correctness of archives, repair mode might
           remove whole archives from the manifest if their archive metadata chunk is
           corrupt or lost. On a chunk level (i.e. the contents of files), repair mode
           will replace corrupt or lost chunks with a same-size replacement chunk of
           zeroes. If a previously zeroed chunk reappears, repair mode will restore
           this lost chunk using the new chunk. Lastly, repair mode will also delete
           orphaned chunks (e.g. caused by read errors while creating the archive).

        Most steps taken by repair mode have a one-time effect on the repository, like
        removing a lost archive from the repository. However, replacing a corrupt or
        lost chunk with an all-zero replacement will have an ongoing effect on the
        repository: When attempting to extract a file referencing an all-zero chunk,
        the ``extract`` command will distinctly warn about it. The FUSE filesystem
        created by the ``mount`` command will reject reading such a "zero-patched"
        file unless a special mount option is given.

        As mentioned earlier, Borg might be able to "heal" a "zero-patched" file in
        repair mode, if all its previously lost chunks reappear (e.g. via a later
        backup). This is achieved by Borg not only keeping track of the all-zero
        replacement chunks, but also by keeping metadata about the lost chunks. In
        repair mode Borg will check whether a previously lost chunk reappeared and will
        replace the all-zero replacement chunk by the reappeared chunk. If all lost
        chunks of a "zero-patched" file reappear, this effectively "heals" the file.
        Consequently, if lost chunks were repaired earlier, it is advised to run
        ``--repair`` a second time after creating some new backups.
        r4  zverify repositoryr  z-repository or archive to check consistency ofz--repository-onlyr0  r  zonly perform repository checksr  z--archives-onlyr3  zonly perform archives checksz--verify-datar/  z`perform cryptographic archive data integrity verification (conflicts with ``--repository-only``)z--repairr'  z+attempt to repair any inconsistencies foundz--save-spacer(  z!work slower, but using less spacez--max-durationr  r)  r   zJdo only a partial repo check for max. SECONDS seconds (Default: unlimited)r  a  
        This command frees repository space by compacting segments.

        Use this regularly to avoid running out of space - you do not need to use this
        after each borg command though. It is especially useful after deleting archives,
        because only compaction will really free repository space.

        borg compact does not need a key, so it is possible to invoke it from the
        client or also from the server.

        Depending on the amount of segments that need compaction, it may take a while,
        so consider using the ``--progress`` option.

        A segment is compacted if the amount of saved space is above the percentage value
        given by the ``--threshold`` option. If omitted, a threshold of 10% is used.
        When using ``--verbose``, borg will output an estimate of the freed space.

        After upgrading borg (server) to 1.2+, you can use ``borg compact --cleanup-commits``
        to clean up the numerous 17byte commit-only segments that borg 1.1 did not clean up
        due to a bug. It is enough to do that once per repository. After cleaning up the
        commits, borg will also do a normal compaction.

        See :ref:`separate_compaction` in Additional Notes for more details.
        r  z*compact segment files / free space in repozrepository to compactz--cleanup-commitsr  z)cleanup commit-only 17-byte segment filesz--thresholdPERCENTr  rr  z>set minimum threshold for saved space in PERCENT (Default: 10)a  
        This command gets and sets options in a local repository or cache config file.
        For security reasons, this command only works on local repositories.

        To delete a config value entirely, use ``--delete``. To list the values
        of the configuration file or the default values, use ``--list``.  To get and existing
        key, pass only the key name. To set a key, pass both the key name and
        the new value. Keys can be specified in the format "section.name" or
        simply "name"; the section will default to "repository" and "cache" for
        the repo and cache configs, respectively.


        By default, borg config manipulates the repository config file. Using ``--cache``
        edits the repository cache's config file instead.
        r  z get and set configuration valuesz-cz--cacher   z&get and set values from the repo cachez-dz--deleterO  z#delete the key from the config filez-lz--listr   z"list the configuration of the repor   )r   r   zrepository to configurer   r  zname of config key)r  r  r  r"  ZVALUEznew value for keyai&  
        This command creates a backup archive containing all files found while recursively
        traversing all paths specified. Paths are added to the archive as they are given,
        that means if relative paths are desired, the command has to be run from the correct
        directory.

        When giving '-' as path, borg will read data from standard input and create a
        file 'stdin' in the created archive from that data. In some cases it's more
        appropriate to use --content-from-command, however. See section *Reading from
        stdin* below for details.

        The archive will consume almost no disk space for files or parts of files that
        have already been stored in other archives.

        The archive name needs to be unique. It must not end in '.checkpoint' or
        '.checkpoint.N' (with N being a number), because these names are used for
        checkpoints and treated in special ways.

        In the archive name, you may use the following placeholders:
        {now}, {utcnow}, {fqdn}, {hostname}, {user} and some others.

        Backup speed is increased by not reprocessing files that are already part of
        existing archives and weren't modified. The detection of unmodified files is
        done by comparing multiple file metadata values with previous values kept in
        the files cache.

        This comparison can operate in different modes as given by ``--files-cache``:

        - ctime,size,inode (default)
        - mtime,size,inode (default behaviour of borg versions older than 1.1.0rc4)
        - ctime,size (ignore the inode number)
        - mtime,size (ignore the inode number)
        - rechunk,ctime (all files are considered modified - rechunk, cache ctime)
        - rechunk,mtime (all files are considered modified - rechunk, cache mtime)
        - disabled (disable the files cache, all files considered modified - rechunk)

        inode number: better safety, but often unstable on network filesystems

        Normally, detecting file modifications will take inode information into
        consideration to improve the reliability of file change detection.
        This is problematic for files located on sshfs and similar network file
        systems which do not provide stable inode numbers, such files will always
        be considered modified. You can use modes without `inode` in this case to
        improve performance, but reliability of change detection might be reduced.

        ctime vs. mtime: safety vs. speed

        - ctime is a rather safe way to detect changes to a file (metadata and contents)
          as it can not be set from userspace. But, a metadata-only change will already
          update the ctime, so there might be some unnecessary chunking/hashing even
          without content changes. Some filesystems do not support ctime (change time).
          E.g. doing a chown or chmod to a file will change its ctime.
        - mtime usually works and only updates if file contents were changed. But mtime
          can be arbitrarily set from userspace, e.g. to set mtime back to the same value
          it had before a content change happened. This can be used maliciously as well as
          well-meant, but in both cases mtime based cache modes can be problematic.

        The mount points of filesystems or filesystem snapshots should be the same for every
        creation of a new archive to ensure fast operation. This is because the file cache that
        is used to determine changed files quickly uses absolute filenames.
        If this is not possible, consider creating a bind mount to a stable location.

        The ``--progress`` option shows (from left to right) Original, Compressed and Deduplicated
        (O, C and D, respectively), then the Number of files (N) processed so far, followed by
        the currently processed path.

        When using ``--stats``, you will get some statistics about how much data was
        added - the "This Archive" deduplicated size there is most interesting as that is
        how much your repository will grow. Please note that the "All archives" stats refer to
        the state after creation. Also, the ``--stats`` and ``--dry-run`` options are mutually
        exclusive because the data is not actually compressed and deduplicated during a dry run.

        For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.

        For more help on placeholders, see the :ref:`borg_placeholders` command output.

        .. man NOTES

        The ``--exclude`` patterns are not like tar. In tar ``--exclude`` .bundler/gems will
        exclude foo/.bundler/gems. In borg it will not, you need to use ``--exclude``
        '\*/.bundler/gems' to get the same effect.

        In addition to using ``--exclude`` patterns, it is possible to use
        ``--exclude-if-present`` to specify the name of a filesystem object (e.g. a file
        or folder name) which, when contained within another folder, will prevent the
        containing folder from being backed up.  By default, the containing folder and
        all of its contents will be omitted from the backup.  If, however, you wish to
        only include the objects specified by ``--exclude-if-present`` in your backup,
        and not include any other contents of the containing folder, this can be enabled
        through using the ``--keep-exclude-tags`` option.

        The ``-x`` or ``--one-file-system`` option excludes directories, that are mountpoints (and everything in them).
        It detects mountpoints by comparing the device number from the output of ``stat()`` of the directory and its
        parent directory. Specifically, it excludes directories for which ``stat()`` reports a device number different
        from the device number of their parent.
        In general: be aware that there are directories with device number different from their parent, which the kernel
        does not consider a mountpoint and also the other way around.
        Linux examples for this are bind mounts (possibly same device number, but always a mountpoint) and ALL
        subvolumes of a btrfs (different device number from parent but not necessarily a mountpoint).
        macOS examples are the apfs mounts of a typical macOS installation.
        Therefore, when using ``--one-file-system``, you should double-check that the backup works as intended.


        .. _list_item_flags:

        Item flags
        ++++++++++

        ``--list`` outputs a list of all files, directories and other
        file system items it considered (no matter whether they had content changes
        or not). For each item, it prefixes a single-letter flag that indicates type
        and/or status of the item.

        If you are interested only in a subset of that output, you can give e.g.
        ``--filter=AME`` and it will only show regular files with A, M or E status (see
        below).

        A uppercase character represents the status of a regular file relative to the
        "files" cache (not relative to the repo -- this is an issue if the files cache
        is not used). Metadata is stored in any case and for 'A' and 'M' also new data
        chunks are stored. For 'U' all data chunks refer to already existing chunks.

        - 'A' = regular file, added (see also :ref:`a_status_oddity` in the FAQ)
        - 'M' = regular file, modified
        - 'U' = regular file, unchanged
        - 'C' = regular file, it changed while we backed it up
        - 'E' = regular file, an error happened while accessing/reading *this* file

        A lowercase character means a file type other than a regular file,
        borg usually just stores their metadata:

        - 'd' = directory
        - 'b' = block device
        - 'c' = char device
        - 'h' = regular file, hardlink (to already seen inodes)
        - 's' = symlink
        - 'f' = fifo

        Other flags used include:

        - 'i' = backup data was read from standard input (stdin)
        - '-' = dry run, item was *not* backed up
        - 'x' = excluded, item was *not* backed up
        - '?' = missing status code (if you see this, please file a bug report!)

        Reading from stdin
        ++++++++++++++++++

        There are two methods to read from stdin. Either specify ``-`` as path and
        pipe directly to borg::

            backup-vm --id myvm --stdout | borg create REPO::ARCHIVE -

        Or use ``--content-from-command`` to have Borg manage the execution of the
        command and piping. If you do so, the first PATH argument is interpreted
        as command to execute and any further arguments are treated as arguments
        to the command::

            borg create --content-from-command REPO::ARCHIVE -- backup-vm --id myvm --stdout

        ``--`` is used to ensure ``--id`` and ``--stdout`` are **not** considered
        arguments to ``borg`` but rather ``backup-vm``.

        The difference between the two approaches is that piping to borg creates an
        archive even if the command piping to borg exits with a failure. In this case,
        **one can end up with truncated output being backed up**. Using
        ``--content-from-command``, in contrast, borg is guaranteed to fail without
        creating an archive should the command fail. The command is considered failed
        when it returned a non-zero exit code.

        Reading from stdin yields just a stream of data without file metadata
        associated with it, and the files cache is not needed at all. So it is
        safe to disable it via ``--files-cache disabled`` and speed up backup
        creation a bit.

        By default, the content read from stdin is stored in a file called 'stdin'.
        Use ``--stdin-name`` to change the name.
        r   zcreate backupz-nrR  r  zdo not create a backup archivez-sz--statsr  z(print statistics for the created archiver   z/output verbose list of items (files, dirs, ...)z--filterZSTATUSCHARSr   zEonly display items with the given status characters (see description))r  r   r  r  z--jsonz*output stats as JSON. Implies ``--stats``.r  z--no-cache-syncr  zNexperimental: do not synchronize the cache. Implies not using the files cache.z--stdin-namer  r  z9use NAME in archive for stdin data (default: %(default)r)r  z--stdin-userZUSERr  z>set user USER in archive for stdin data (default: %(default)r)z--stdin-groupZGROUPr  z@set group GROUP in archive for stdin data (default: %(default)r)z--stdin-moder  r  c                 S   r  r  r  r  r   r   r   rD  M  r  z'Archiver.build_parser.<locals>.<lambda>z@set mode to M in archive for stdin data (default: %(default)04o)z--content-from-commandzZinterpret PATH as command and store its stdout. See also section Reading from stdin below.z--paths-from-stdinzread DELIM-separated list of paths to backup from stdin. All control is external: it will back up all files given - no more, no less.z--paths-from-commandzHinterpret PATH as command and treat its output as ``--paths-from-stdin``z--paths-delimiterZDELIMz\set path delimiter for ``--paths-from-stdin`` and ``--paths-from-command`` (default: ``\n``))r  z--exclude-nodumpr  zexclude files flagged NODUMPzFilesystem optionsz-xz--one-file-systemr  zstay in the same file system and do not store mount points of other file systems - this might behave different from your expectations, see the description below.r  r   r  r  z-only store numeric user and group identifiersr  r  zdo not store atime into archivez--atimer  zdo store atime into archivez	--noctimer  zdo not store ctime into archivez--nobirthtimer  z3do not store birthtime (creation date) into archiver  r   z%deprecated, use ``--noflags`` insteadz	--noflagsr   zAdo not read and store flags (e.g. NODUMP, IMMUTABLE) into archivez--noaclsr   z'do not read and store ACLs into archivez
--noxattrsr   z)do not read and store xattrs into archivez--sparser  z>detect sparse holes in input (supported only by fixed chunker)z--files-cacheZMODEr   z(operate files cache in MODE. default: %s)r  r   r  r   r   r  z--read-specialr  zopen and read block and char device files as well as FIFOs as if they were regular files. Also follows symlinks pointing to these kinds of files.zArchive optionsz	--commentr  COMMENTz!add a comment text to the archive)r   r  r   r   r  z--timestamp	TIMESTAMPrJ   zmanually specify the archive creation date/time (UTC, yyyy-mm-ddThh:mm:ss format). Alternatively, give a reference file/directory.z--checkpoint-intervalr  i  z6write checkpoint every SECONDS seconds (Default: 1800)z--chunker-paramsZPARAMSr  z~specify the chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, HASH_MASK_BITS, HASH_WINDOW_SIZE). default: %s,%d,%d,%d,%d)r  r   r   r   r  r  z-Cz--compressionZCOMPRESSIONr   lz4z`select compression algorithm, see the output of the "borg help compression" command for details.ZARCHIVEz?name of archive to create (must be also a valid directory name)r  r    r  zpaths to archive)r  r  r   r  r  al  
        These commands are not intended for normal use and potentially very
        dangerous if used incorrectly.

        They exist to improve debugging capabilities without direct system access, e.g.
        in case you ever run into some severe malfunction. Use them only if you know
        what you are doing or if a trusted developer tells you what to do.r  z/debugging command (not intended for normal use)z
        This command displays some system information that might be useful for bug
        reports and debugging problems. If a traceback happens, this information is
        already appended at the end of the traceback.
        r  z5show system infos for debugging / bug reports (debug)zq
        This command dumps raw (but decrypted and decompressed) archive items (only metadata) to files.
        zdump-archive-itemsz%dump archive items (metadata) (debug)zarchive to dumpz\
        This command dumps all metadata of an archive in a decoded form to a file.
        zdump-archivez%dump decoded archive metadata (debug)zfile to dump data intozc
        This command dumps manifest metadata of a repository in a decoded form to a file.
        zdump-manifestz(dump decoded repository metadata (debug)zrepository to dumpz`
        This command dumps raw (but decrypted and decompressed) repo objects to files.
        zdump-repo-objszdump repo objects (debug)z--ghostrX  zRdump all segment file contents, including deleted/uncommitted objects and commits.z	--segmentZSEGrM  z>used together with --ghost: limit processing to given segment.r  z--offsetZOFFSrN  z=used together with --ghost: limit processing to given offset.zx
        This command searches raw (but decrypted and decompressed) repo objects for a specific bytes sequence.
        zsearch-repo-objszsearch repo objects (debug)zrepository to searchr^  ZWANTEDzCterm to search the repo for, either 0x1234abcd hex term or a stringzJ
        This command computes the id-hash for some file content.
        zid-hashz-compute id-hash for some file content (debug)zrepository to usez0content for which the id-hash shall get computedzB
        This command gets an object from the repository.
        zget-objz"get object from repository (debug)rK  IDz"hex object ID to get from the repozfile to write object data intozB
        This command puts an object into the repository.
        zput-objz put object to repository (debug)z"hex object ID to put into the repoz#file to read and create object fromzC
        This command deletes objects from the repository.
        z
delete-objz%delete object from repository (debug)rZ  ZIDs+z(hex object ID(s) to delete from the repor  z\
        This command displays the reference count for objects from the repository.
        zrefcount-objz0show refcount for object from repository (debug)z&hex object ID(s) to show refcounts forz?
        This command dumps the repository hints data.
        z
dump-hintszdump repo hints (debug)zQ
        Convert a Borg profile to a Python cProfile compatible profile.
        zconvert-profilez.convert Borg profile to Python profile (debug)r  ZINPUTr  zBorg profiler$  ZOUTPUTr5  zOutput fileaB  
        This command deletes an archive from the repository or the complete repository.

        Important: When deleting archives, repository disk space is **not** freed until
        you run ``borg compact``.

        When you delete a complete repository, the security info and local cache for it
        (if any) are also deleted. Alternatively, you can delete just the local cache
        with the ``--cache-only`` option, or keep the security info with the
        ``--keep-security-info`` option.

        When in doubt, use ``--dry-run --list`` to see what would be deleted.

        When using ``--stats``, you will get some statistics about how much data was
        deleted - the "Deleted data" deduplicated size there is most interesting as
        that is how much your repository will shrink.
        Please note that the "All archives" stats refer to the state after deletion.

        You can delete multiple archives by specifying a shell pattern to match
        multiple archives using the ``--glob-archives GLOB`` option (for more info on
        these patterns, see :ref:`borg_patterns`).

        To avoid accidentally deleting archives, especially when using glob patterns,
        it might be helpful to use the ``--dry-run`` to test out the command without
        actually making any changes to the repository.
        zdelete archivezdo not change repositoryzoutput verbose list of archivesz(print statistics for the deleted archivez--cache-onlyr  z4delete only the local cache for the given repositoryz--forcer  rj  z`force deletion of corrupted archives, use ``--force --force`` in case ``--force`` does not work.r  z--keep-security-infor  z7keep the local security info when deleting a repositoryzrepository or archive to deleter  zarchives to deletea  
            This command finds differences (file contents, user/group/mode) between archives.

            A repository location and an archive name must be specified for REPO::ARCHIVE1.
            ARCHIVE2 is just another archive name in same repository (no repository location
            allowed).

            For archives created with Borg 1.1 or newer diff automatically detects whether
            the archives are created with the same chunker params. If so, only chunk IDs
            are compared, which is very fast.

            For archives prior to Borg 1.1 chunk contents are compared by default.
            If you did not create the archives with different chunker params,
            pass ``--same-chunker-params``.
            Note that the chunker params changed from Borg 0.xx to 1.0.

            For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.
            rm  z$find differences in archive contentsz0only consider numeric user and group identifiersz--same-chunker-paramsrx  z%Override check of chunker parameters.z--sortry  z#Sort the output lines by file path.z--content-onlyzBOnly compare differences in content (exclude metadata differences)z--json-lineszFormat output as JSON Lines. zREPO::ARCHIVE1z%repository location and ARCHIVE1 namerv  ZARCHIVE2z.ARCHIVE2 name (no repository location allowed)zEpaths of items inside the archives to compare; patterns are supportedaJ  
        This command creates a tarball from an archive.

        When giving '-' as the output FILE, Borg will write a tar stream to standard output.

        By default (``--tar-filter=auto``) Borg will detect whether the FILE should be compressed
        based on its file extension and pipe the tarball through an appropriate filter
        before writing it to FILE:

        - .tar.gz or .tgz: gzip
        - .tar.bz2 or .tbz: bzip2
        - .tar.xz or .txz: xz
        - .tar.zstd or .tar.zst: zstd
        - .tar.lz4: lz4

        Alternatively, a ``--tar-filter`` program may be explicitly specified. It should
        read the uncompressed tar stream from stdin and write a compressed/filtered
        tar stream to stdout.

        The generated tarball uses the GNU tar format.

        export-tar is a lossy conversion:
        BSD flags, ACLs, extended attributes (xattrs), atime and ctime are not exported.
        Timestamp resolution is limited to whole seconds, not the nanosecond resolution
        otherwise supported by Borg.

        A ``--sparse`` option (as found in borg extract) is not supported.

        By default the entire archive is extracted but a subset of files and directories
        can be selected by passing a list of ``PATHs`` as arguments.
        The file selection can further be restricted by using the ``--exclude`` option.

        For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.

        ``--progress`` can be slower than no progress display, since it makes one additional
        pass over the archive metadata.
        z
export-tarzcreate tarball from archivez--tar-filterr8  r2  z#filter program to pipe data through)r   r   r  zarchive to exportr9  r  z0output tar file. "-" to write to stdout instead.r  r  a  
        This command extracts the contents of an archive. By default the entire
        archive is extracted but a subset of files and directories can be selected
        by passing a list of ``PATHs`` as arguments. The file selection can further
        be restricted by using the ``--exclude`` option.

        For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.

        By using ``--dry-run``, you can do all extraction steps except actually writing the
        output data: reading metadata and data chunks from the repo, checking the hash/hmac,
        decrypting, decompressing.

        ``--progress`` can be slower than no progress display, since it makes one additional
        pass over the archive metadata.

        .. note::

            Currently, extract always writes into the current working directory ("."),
            so make sure you ``cd`` to the right place before calling ``borg extract``.

            When parent directories are not extracted (because of using file/directory selection
            or any other reason), borg can not restore parent directories' metadata, e.g. owner,
            group, permission, etc.
        rQ  zextract archive contentsz do not actually change any filesz,only obey numeric user and group identifiersz1do not extract/set flags (e.g. NODUMP, IMMUTABLE)zdo not extract/set ACLszdo not extract/set xattrsz--stdoutr  z"write all extracted data to stdoutz7create holes in output sparse file from all-zero chunkszarchive to extractr  z
Extra help)r  r  r  z--epilog-onlyr  )r   r  z--usage-onlyr  r  r  zadditional help on TOPIC)r  r   r  r  a{  
        This command displays detailed information about the specified archive or repository.

        Please note that the deduplicated sizes of the individual archives do not add
        up to the deduplicated size of the repository ("all archives"), because the two
        are meaning different things:

        This archive / deduplicated size = amount of data stored ONLY for this archive
        = unique chunks of this archive.
        All archives / deduplicated size = amount of data stored in the repo
        = all chunks in the repository.

        Borg archives can only contain a limited amount of file metadata.
        The size of an archive relative to this limit depends on a number of factors,
        mainly the number of files, the lengths of paths and other metadata stored for files.
        This is shown as *utilization of maximum supported archive size*.
        z&show repository or archive informationz2repository or archive to display information aboutzformat output as JSONa/  
        This command initializes an empty repository. A repository is a filesystem
        directory containing the deduplicated data from zero or more archives.

        Encryption mode TLDR
        ++++++++++++++++++++

        The encryption mode can only be configured when creating a new repository -
        you can neither configure it on a per-archive basis nor change the
        encryption mode of an existing repository.

        Use ``repokey``::

            borg init --encryption repokey /path/to/repo

        Or ``repokey-blake2`` depending on which is faster on your client machines (see below)::

            borg init --encryption repokey-blake2 /path/to/repo

        Borg will:

        1. Ask you to come up with a passphrase.
        2. Create a borg key (which contains 3 random secrets. See :ref:`key_files`).
        3. Encrypt the key with your passphrase.
        4. Store the encrypted borg key inside the repository directory (in the repo config).
           This is why it is essential to use a secure passphrase.
        5. Encrypt and sign your backups to prevent anyone from reading or forging them unless they
           have the key and know the passphrase. Make sure to keep a backup of
           your key **outside** the repository - do not lock yourself out by
           "leaving your keys inside your car" (see :ref:`borg_key_export`).
           For remote backups the encryption is done locally - the remote machine
           never sees your passphrase, your unencrypted key or your unencrypted files.
           Chunking and id generation are also based on your key to improve
           your privacy.
        6. Use the key when extracting files to decrypt them and to verify that the contents of
           the backups have not been accidentally or maliciously altered.

        Picking a passphrase
        ++++++++++++++++++++

        Make sure you use a good passphrase. Not too short, not too simple. The real
        encryption / decryption key is encrypted with / locked by your passphrase.
        If an attacker gets your key, he can't unlock and use it without knowing the
        passphrase.

        Be careful with special or non-ascii characters in your passphrase:

        - Borg processes the passphrase as unicode (and encodes it as utf-8),
          so it does not have problems dealing with even the strangest characters.
        - BUT: that does not necessarily apply to your OS / VM / keyboard configuration.

        So better use a long passphrase made from simple ascii chars than one that
        includes non-ascii stuff or characters that are hard/impossible to enter on
        a different keyboard layout.

        You can change your passphrase for existing repos at any time, it won't affect
        the encryption/decryption key or other secrets.

        More encryption modes
        +++++++++++++++++++++

        Only use ``--encryption none`` if you are OK with anyone who has access to
        your repository being able to read your backups and tamper with their
        contents without you noticing.

        If you want "passphrase and having-the-key" security, use ``--encryption keyfile``.
        The key will be stored in your home directory (in ``~/.config/borg/keys``).

        If you do **not** want to encrypt the contents of your backups, but still
        want to detect malicious tampering use ``--encryption authenticated``.
        To normally work with ``authenticated`` repos, you will need the passphrase, but
        there is an emergency workaround, see ``BORG_WORKAROUNDS=authenticated_no_key`` docs.

        If ``BLAKE2b`` is faster than ``SHA-256`` on your hardware, use ``--encryption authenticated-blake2``,
        ``--encryption repokey-blake2`` or ``--encryption keyfile-blake2``. Note: for remote backups
        the hashing is done on your local machine.

        .. nanorst: inline-fill

        +----------+---------------+------------------------+--------------------------+
        | Hash/MAC | Not encrypted | Not encrypted,         | Encrypted (AEAD w/ AES)  |
        |          | no auth       | but authenticated      | and authenticated        |
        +----------+---------------+------------------------+--------------------------+
        | SHA-256  | none          | `authenticated`        | repokey                  |
        |          |               |                        | keyfile                  |
        +----------+---------------+------------------------+--------------------------+
        | BLAKE2b  | n/a           | `authenticated-blake2` | `repokey-blake2`         |
        |          |               |                        | `keyfile-blake2`         |
        +----------+---------------+------------------------+--------------------------+

        .. nanorst: inline-replace

        Modes `marked like this` in the above table are new in Borg 1.1 and are not
        backwards-compatible with Borg 1.0.x.

        On modern Intel/AMD CPUs (except very cheap ones), AES is usually
        hardware-accelerated.
        BLAKE2b is faster than SHA256 on Intel/AMD 64-bit CPUs
        (except AMD Ryzen and future CPUs with SHA extensions),
        which makes `authenticated-blake2` faster than `none` and `authenticated`.

        On modern ARM CPUs, NEON provides hardware acceleration for SHA256 making it faster
        than BLAKE2b-256 there. NEON accelerates AES as well.

        Hardware acceleration is always used automatically when available.

        `repokey` and `keyfile` use AES-CTR-256 for encryption and HMAC-SHA256 for
        authentication in an encrypt-then-MAC (EtM) construction. The chunk ID hash
        is HMAC-SHA256 as well (with a separate key).
        These modes are compatible with Borg 1.0.x.

        `repokey-blake2` and `keyfile-blake2` are also authenticated encryption modes,
        but use BLAKE2b-256 instead of HMAC-SHA256 for authentication. The chunk ID
        hash is a keyed BLAKE2b-256 hash.
        These modes are new and *not* compatible with Borg 1.0.x.

        `authenticated` mode uses no encryption, but authenticates repository contents
        through the same HMAC-SHA256 hash as the `repokey` and `keyfile` modes (it uses it
        as the chunk ID hash). The key is stored like `repokey`.
        This mode is new and *not* compatible with Borg 1.0.x.

        `authenticated-blake2` is like `authenticated`, but uses the keyed BLAKE2b-256 hash
        from the other blake2 modes.
        This mode is new and *not* compatible with Borg 1.0.x.

        `none` mode uses no encryption and no authentication. It uses SHA256 as chunk
        ID hash. This mode is not recommended, you should rather consider using an authenticated
        or authenticated/encrypted mode. This mode has possible denial-of-service issues
        when running ``borg create`` on contents controlled by an attacker.
        Use it only for new repositories where no encryption is wanted **and** when compatibility
        with 1.0.x is important. If compatibility with 1.0.x is not important, use
        `authenticated-blake2` or `authenticated` instead.
        This mode is compatible with Borg 1.0.x.
        initzinitialize empty repositoryzrepository to creater  z--encryptionr  z)select encryption key mode **(required)**)r  r   requiredchoicesr  z--append-onlyr   zcreate an append-only mode repository. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details.z--storage-quotaZQUOTAr   zKSet storage quota of the new repository (e.g. 5G, 1.5T). Default: no quota.z--make-parent-dirsr   zOcreate the parent directories of the repository directory, if they are missing.r   z+Manage a keyfile or repokey of a repositoryzmanage repository keyaG  
        If repository encryption is used, the repository is inaccessible
        without the key. This command allows one to backup this essential key.
        Note that the backup produced does not include the passphrase itself
        (i.e. the exported key stays encrypted). In order to regain access to a
        repository, one needs both the exported key and the original passphrase.

        There are three backup formats. The normal backup format is suitable for
        digital storage as a file. The ``--paper`` backup format is optimized
        for printing and typing in while importing, with per line checks to
        reduce problems with manual input. The ``--qr-html`` creates a printable
        HTML template with a QR code and a copy of the ``--paper``-formatted key.

        For repositories using keyfile encryption the key is saved locally
        on the system that is capable of doing backups. To guard against loss
        of this key, the key needs to be backed up independently of the main
        data backup.

        For repositories using the repokey encryption the key is saved in the
        repository in the config file. A backup is thus not strictly needed,
        but guards against the repository becoming inaccessible if the file
        is damaged for some reason.

        Examples::

            borg key export /path/to/repo > encrypted-key-backup
            borg key export --paper /path/to/repo > encrypted-key-backup.txt
            borg key export --qr-html /path/to/repo > encrypted-key-backup.html
            # Or pass the output file as an argument instead of redirecting stdout:
            borg key export /path/to/repo encrypted-key-backup
            borg key export --paper /path/to/repo encrypted-key-backup.txt
            borg key export --qr-html /path/to/repo encrypted-key-backup.html


        r?  z export repository key for backup)r  r  r   r   zwhere to store the backupz--paperr=  z8Create an export suitable for printing and later type-inz	--qr-htmlr>  zFCreate an html file suitable for printing and later type-in or qr scana  
        This command restores a key previously backed up with the export command.

        If the ``--paper`` option is given, the import will be an interactive
        process in which each line is checked for plausibility before
        proceeding to the next line. For this format PATH must not be given.

        For repositories using keyfile encryption, the key file which ``borg key
        import`` writes to depends on several factors. If the ``BORG_KEY_FILE``
        environment variable is set and non-empty, ``borg key import`` creates
        or overwrites that file named by ``$BORG_KEY_FILE``. Otherwise, ``borg
        key import`` searches in the ``$BORG_KEYS_DIR`` directory for a key file
        associated with the repository. If a key file is found in
        ``$BORG_KEYS_DIR``, ``borg key import`` overwrites it; otherwise, ``borg
        key import`` creates a new key file in ``$BORG_KEYS_DIR``.
        importz!import repository key from backupz+path to the backup ('-' to read from stdin)z8interactively import from a backup done with ``--paper``a  
        The key files used for repository encryption are optionally passphrase
        protected. This command can be used to change this passphrase.

        Please note that this command only changes the passphrase, but not any
        secret protected by it (like e.g. encryption/MAC keys or chunker seed).
        Thus, changing the passphrase after passphrase and borg key got compromised
        does not protect future (nor past) backups to the same repository.
        zchange-passphrasezchange repository passphrasea  
        This command migrates a repository from passphrase mode (removed in Borg 1.0)
        to repokey mode.

        You will be first asked for the repository passphrase (to open it in passphrase
        mode). This is the same passphrase as you used to use for this repo before 1.0.

        It will then derive the different secrets from this passphrase.

        Then you will be asked for a new passphrase (twice, for safety). This
        passphrase will be used to protect the repokey (which contains these same
        secrets in encrypted form). You may use the same passphrase as you used to
        use, but you may also use a different one.

        After migrating to repokey mode, you can change the passphrase at any time.
        But please note: the secrets will always stay the same and they could always
        be derived from your (old) passphrase-mode passphrase.
        zmigrate-to-repokeyz-migrate passphrase-mode repository to repokeyah  
        This command lists the contents of a repository or an archive.

        For more help on include/exclude patterns, see the :ref:`borg_patterns` command output.

        .. man NOTES

        The FORMAT specifier syntax
        +++++++++++++++++++++++++++

        The ``--format`` option uses python's `format string syntax
        <https://docs.python.org/3.8/library/string.html#formatstrings>`_.

        Examples:
        ::

            $ borg list --format '{archive}{NL}' /path/to/repo
            ArchiveFoo
            ArchiveBar
            ...

            # {VAR:NUMBER} - pad to NUMBER columns.
            # Strings are left-aligned, numbers are right-aligned.
            # Note: time columns except ``isomtime``, ``isoctime`` and ``isoatime`` cannot be padded.
            $ borg list --format '{archive:36} {time} [{id}]{NL}' /path/to/repo
            ArchiveFoo                           Thu, 2021-12-09 10:22:28 [0b8e9a312bef3f2f6e2d0fc110c196827786c15eba0188738e81697a7fa3b274]
            $ borg list --format '{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}' /path/to/repo::ArchiveFoo
            -rw-rw-r-- user   user       1024 Thu, 2021-12-09 10:22:17 file-foo
            ...

            # {VAR:<NUMBER} - pad to NUMBER columns left-aligned.
            # {VAR:>NUMBER} - pad to NUMBER columns right-aligned.
            $ borg list --format '{mode} {user:>6} {group:>6} {size:<8} {mtime} {path}{extra}{NL}' /path/to/repo::ArchiveFoo
            -rw-rw-r--   user   user 1024     Thu, 2021-12-09 10:22:17 file-foo
            ...

        The following keys are always available:


        zN

        Keys available only when listing archives in a repository:

        zI

        Keys available only when listing files in an archive:

        z#list archive or repository contentsr  r  r  r  z--shortr  z-only print file/directory names, nothing elsez--formatZFORMATr@  zspecify format for file or archive listing (default for files: "{mode} {user:6} {group:6} {size:8} {mtime} {path}{extra}{NL}"; for archives: "{archive:<36} {time} [{id}]{NL}")r  a  Only valid for listing repository contents. Format output as JSON. The form of ``--format`` is ignored, but keys used in it are added to the JSON output. Some keys are always present. Note: JSON can only represent text. A "barchive" key is therefore not available.a  Only valid for listing archive contents. Format output as JSON Lines. The form of ``--format`` is ignored, but keys used in it are added to the JSON output. Some keys are always present. Note: JSON can only represent text. A "bpath" key is therefore not available.z)repository or archive to list contents ofz%paths to list; patterns are supportedr  a  
        The prune command prunes a repository by deleting all archives not matching
        any of the specified retention options.

        Important: Repository disk space is **not** freed until you run ``borg compact``.

        This command is normally used by automated backup scripts wanting to keep a
        certain number of historic backups. This retention policy is commonly referred to as
        `GFS <https://en.wikipedia.org/wiki/Backup_rotation_scheme#Grandfather-father-son>`_
        (Grandfather-father-son) backup rotation scheme.

        Also, prune automatically removes checkpoint archives (incomplete archives left
        behind by interrupted backup runs) except if the checkpoint is the latest
        archive (and thus still needed). Checkpoint archives are not considered when
        comparing archive counts against the retention limits (``--keep-X``).

        If a prefix is set with -P, then only archives that start with the prefix are
        considered for deletion and only those archives count towards the totals
        specified by the rules.
        Otherwise, *all* archives in the repository are candidates for deletion!
        There is no automatic distinction between archives representing different
        contents. These need to be distinguished by specifying matching prefixes.

        If you have multiple sequences of archives with different data sets (e.g.
        from different machines) in one shared repository, use one prune call per
        data set that matches only the respective archives using the -P option.

        The ``--keep-within`` option takes an argument of the form "<int><char>",
        where char is "H", "d", "w", "m", "y". For example, ``--keep-within 2d`` means
        to keep all archives that were created within the past 48 hours.
        "1m" is taken to mean "31d". The archives kept with this option do not
        count towards the totals specified by any other options.

        A good procedure is to thin out more and more the older your backups get.
        As an example, ``--keep-daily 7`` means to keep the latest backup on each day,
        up to 7 most recent days with backups (days without backups do not count).
        The rules are applied from secondly to yearly, and backups selected by previous
        rules do not count towards those of later rules. The time that each backup
        starts is used for pruning purposes. Dates and times are interpreted in
        the local timezone, and weeks go from Monday to Sunday. Specifying a
        negative number of archives to keep means that there is no limit. As of borg
        1.2.0, borg will retain the oldest archive if any of the secondly, minutely,
        hourly, daily, weekly, monthly, or yearly rules was not otherwise able to meet
        its retention target. This enables the first chronological archive to continue
        aging until it is replaced by a newer archive that meets the retention criteria.

        The ``--keep-last N`` option is doing the same as ``--keep-secondly N`` (and it will
        keep the last N archives under the assumption that you do not create more than one
        backup archive in the same second).

        When using ``--stats``, you will get some statistics about how much data was
        deleted - the "Deleted data" deduplicated size there is most interesting as
        that is how much your repository will shrink.
        Please note that the "All archives" stats refer to the state after pruning.
        r  zprune archivesz_force pruning of corrupted archives, use ``--force --force`` in case ``--force`` does not work.z/output verbose list of archives it keeps/prunesz--keep-withinZINTERVALr  z+keep all archives within this time intervalr  z--keep-lastz--keep-secondlyr  z#number of secondly archives to keep)r   r   r   r  z--keep-minutelyr  z#number of minutely archives to keepz-Hz--keep-hourlyr  z!number of hourly archives to keepz--keep-dailyr  z number of daily archives to keepz-wz--keep-weeklyr  z!number of weekly archives to keepz-mz--keep-monthlyr  z"number of monthly archives to keepz-yz--keep-yearlyr  z!number of yearly archives to keepzrepository to prunea7  
        Recreate the contents of existing archives.

        recreate is a potentially dangerous function and might lead to data loss
        (if used wrongly). BE VERY CAREFUL!

        Important: Repository disk space is **not** freed until you run ``borg compact``.

        ``--exclude``, ``--exclude-from``, ``--exclude-if-present``, ``--keep-exclude-tags``
        and PATH have the exact same semantics as in "borg create", but they only check
        for files in the archives and not in the local file system. If PATHs are specified,
        the resulting archives will only contain files from these PATHs.

        Note that all paths in an archive are relative, therefore absolute patterns/paths
        will *not* match (``--exclude``, ``--exclude-from``, PATHs).

        ``--recompress`` allows one to change the compression of existing data in archives.
        Due to how Borg stores compressed size information this might display
        incorrect information for archives that were not recreated at the same time.
        There is no risk of data loss by this.

        ``--chunker-params`` will re-chunk all files in the archive, this can be
        used to have upgraded Borg 0.xx or Attic archives deduplicate with
        Borg 1.x archives.

        **USE WITH CAUTION.**
        Depending on the PATHs and patterns given, recreate can be used to permanently
        delete files from archives.
        When in doubt, use ``--dry-run --verbose --list`` to see how patterns/PATHS are
        interpreted. See :ref:`list_item_flags` in ``borg create`` for details.

        The archive being recreated is only removed after the operation completes. The
        archive that is built during the operation exists at the same time at
        "<ARCHIVE>.recreate". The new archive will have a different archive ID.

        With ``--target`` the original archive is not replaced, instead a new archive is created.

        When rechunking (or recompressing), space usage can be substantial - expect
        at least the entire deduplicated size of the archives using the previous
        chunker (or compression) params.

        If you recently ran borg check --repair and it had to fix lost chunks with all-zero
        replacement chunks, please first run another backup for the same data and re-run
        borg check --repair afterwards to heal any archives that had lost chunks which are
        still generated from the input data.

        Important: running borg recreate to re-chunk will remove the chunks_healthy
        metadata of all items with replacement chunks, so healing will not be possible
        any more after re-chunking (it is also unlikely it would ever work: due to the
        change of chunking parameters, the missing chunk likely will never be seen again
        even if you still have the data that produced it).
        r  zRonly display items with the given status characters (listed in borg create --help)zdo not change anythingzprint statistics at endz--targetrJ  ZTARGETzocreate a new archive with the name ARCHIVE, do not replace existing archive (only applies for a single archive))r   r  r   r   r  )r   r   r   r  r  zmanually specify the archive creation date/time (UTC, yyyy-mm-ddThh:mm:ss format). alternatively, give a reference file/directory.z--recompressr  r  if-different)r  r  r  a  recompress data chunks according to `MODE` and ``--compression``. Possible modes are `if-different`: recompress if current compression is with a different compression algorithm (the level is not considered); `always`: recompress even if current compression is with the same compression algorithm (use this to change the compression level); and `never`: do not recompress (use this option to explicitly prevent recompression). If no MODE is given, `if-different` will be used. Not passing --recompress is equivalent to "--recompress never".)r  r   r  r   r  r  r  zrechunk using given chunker parameters (ALGO, CHUNK_MIN_EXP, CHUNK_MAX_EXP, HASH_MASK_BITS, HASH_WINDOW_SIZE) or `default` to use the chunker defaults. default: do not rechunkz!repository or archive to recreatez)paths to recreate; patterns are supportedzu
        This command renames an archive in the repository.

        This results in a different archive ID.
        r|  zrename archivezarchive to renameZNEWNAMEzthe new archive name to usezm
        This command starts a repository server process. This command is usually not used manually.
        r  zstart repository server processz--restrict-to-pathr  r)  zrestrict repository access to PATH. Can be specified multiple times to allow the client access to several directories. Access to all sub-directories is granted implicitly; PATH doesn't need to directly point to a repository.z--restrict-to-repositoryr  a  restrict repository access. Only the repository located at PATH (no sub-directories are considered) is accessible. Can be specified multiple times to allow the client access to several repositories. Unlike ``--restrict-to-path`` sub-directories are not accessible; PATH needs to directly point at a repository location. PATH may be an empty directory or the last element of PATH may not exist, in which case the client may initialize a repository there.zonly allow appending to repository segment files. Note that this only affects the low level structure of the repository, and running `delete` or `prune` will still be allowed. See :ref:`append_only_mode` in Additional Notes for more details.zOverride storage quota of the repository (e.g. 5G, 1.5T). When a new repository is initialized, sets the storage quota on the new repository as well. Default: no quota.z
        This command un-mounts a FUSE filesystem that was mounted with ``borg mount``.

        This is a convenience wrapper that just calls the platform-specific shell
        command - usually this is either umount or fusermount -u.
        ri   zumount repositoryr  r  z&mountpoint of the filesystem to umountal  
        Upgrade an existing, local Borg repository.

        When you do not need borg upgrade
        +++++++++++++++++++++++++++++++++

        Not every change requires that you run ``borg upgrade``.

        You do **not** need to run it when:

        - moving your repository to a different place
        - upgrading to another point release (like 1.0.x to 1.0.y),
          except when noted otherwise in the changelog
        - upgrading from 1.0.x to 1.1.x,
          except when noted otherwise in the changelog

        Borg 1.x.y upgrades
        +++++++++++++++++++

        Archive TAM authentication:

        Use ``borg upgrade --archives-tam REPO`` to add archive TAMs to all
        archives that are not TAM authenticated yet.
        This is a convenient method to just trust all archives present - if
        an archive does not have TAM authentication yet, a TAM will be added.
        Archives created by old borg versions < 1.0.9 do not have TAMs.
        Archives created by newer borg version should have TAMs already.
        If you have a high risk environment, you should not just run this,
        but first verify that the archives are authentic and not malicious
        (== have good content, have a good timestamp).
        Borg 1.2.5+ needs all archives to be TAM authenticated for safety reasons.

        This upgrade needs to be done once per repository.

        Manifest TAM authentication:

        Use ``borg upgrade --tam REPO`` to require manifest authentication
        introduced with Borg 1.0.9 to address security issues. This means
        that modifying the repository after doing this with a version prior
        to 1.0.9 will raise a validation error, so only perform this upgrade
        after updating all clients using the repository to 1.0.9 or newer.

        This upgrade should be done on each client for safety reasons.

        If a repository is accidentally modified with a pre-1.0.9 client after
        this upgrade, use ``borg upgrade --tam --force REPO`` to remedy it.

        If you routinely do this you might not want to enable this upgrade
        (which will leave you exposed to the security issue). You can
        reverse the upgrade by issuing ``borg upgrade --disable-tam REPO``.

        See
        https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability
        for details.

        Attic and Borg 0.xx to Borg 1.x
        +++++++++++++++++++++++++++++++

        This currently supports converting an Attic repository to Borg and also
        helps with converting Borg 0.xx to 1.0.

        Currently, only LOCAL repositories can be upgraded (issue #465).

        Please note that ``borg create`` (since 1.0.0) uses bigger chunks by
        default than old borg or attic did, so the new chunks won't deduplicate
        with the old chunks in the upgraded repository.
        See ``--chunker-params`` option of ``borg create`` and ``borg recreate``.

        ``borg upgrade`` will change the magic strings in the repository's
        segments to match the new Borg magic strings. The keyfiles found in
        $ATTIC_KEYS_DIR or ~/.attic/keys/ will also be converted and
        copied to $BORG_KEYS_DIR or ~/.config/borg/keys.

        The cache files are converted, from $ATTIC_CACHE_DIR or
        ~/.cache/attic to $BORG_CACHE_DIR or ~/.cache/borg, but the
        cache layout between Borg and Attic changed, so it is possible
        the first backup after the conversion takes longer than expected
        due to the cache resync.

        Upgrade should be able to resume if interrupted, although it
        will still iterate over all segments. If you want to start
        from scratch, use `borg delete` over the copied repository to
        make sure the cache files are also removed::

            borg delete borg

        Unless ``--inplace`` is specified, the upgrade process first creates a backup
        copy of the repository, in REPOSITORY.before-upgrade-DATETIME, using hardlinks.
        This requires that the repository and its parent directory reside on same
        filesystem so the hardlink copy can work.
        This takes longer than in place upgrades, but is much safer and gives
        progress information (as opposed to ``cp -al``). Once you are satisfied
        with the conversion, you can safely destroy the backup copy.

        WARNING: Running the upgrade in place will make the current
        copy unusable with older version, with no way of going back
        to previous versions. This can PERMANENTLY DAMAGE YOUR
        REPOSITORY!  Attic CAN NOT READ BORG REPOSITORIES, as the
        magic strings have changed. You have been warned.r  zupgrade repository formatz	--inplacer  z^rewrite repository in place, with no chance of going back to older versions of the repository.r  zForce upgradez--tamr  zIEnable manifest authentication (in key and cache) (Borg 1.0.9 and later).z--disable-tamr  z3Disable manifest authentication (in key and cache).z--archives-tamr  z(add TAM authentication for all archives.z%path to the repository to be upgradeda  
        This command runs a user-specified command while the repository lock is held.

        It will first try to acquire the lock (make sure that no other operation is
        running in the repo), then execute the given command as a subprocess and wait
        for its termination, release the lock and return the user command's return
        code as borg's return code.

        .. note::

            If you copy a repository with the lock held, the lock will be present in
            the copy. Thus, before using borg on the copy from a different host,
            you need to use "borg break-lock" on the copied repository, because
            Borg is cautious and does not automatically remove stale locks made by a different host.
        z	with-lockzrun user command with lock heldzrepository to lockr  ZCOMMANDzcommand to runr   ZARGSzcommand argumentsa  
        This command creates a backup archive from a tarball.

        When giving '-' as path, Borg will read a tar stream from standard input.

        By default (--tar-filter=auto) Borg will detect whether the file is compressed
        based on its file extension and pipe the file through an appropriate filter:

        - .tar.gz or .tgz: gzip -d
        - .tar.bz2 or .tbz: bzip2 -d
        - .tar.xz or .txz: xz -d
        - .tar.zstd or .tar.zst: zstd -d
        - .tar.lz4: lz4 -d

        Alternatively, a --tar-filter program may be explicitly specified. It should
        read compressed data from stdin and output an uncompressed tar stream on
        stdout.

        Most documentation of borg create applies. Note that this command does not
        support excluding files.

        import-tar is a lossy conversion:
        BSD flags, ACLs, extended attributes (xattrs), atime and ctime are not exported.
        Timestamp resolution is limited to whole seconds, not the nanosecond resolution
        otherwise supported by Borg.

        A ``--sparse`` option (as found in borg create) is not supported.

        import-tar reads POSIX.1-1988 (ustar), POSIX.1-2001 (pax), GNU tar, UNIX V7 tar
        and SunOS tar with extended attributes.

        To import multiple tarballs into a single archive, they can be simply
        concatenated (e.g. using "cat") into a single file, and imported with an
        ``--ignore-zeros`` option to skip through the stop markers between them.
        z
import-tar)r   r   r  r  z3only display items with the given status characters)r   r  r  r  z&output stats as JSON (implies --stats)z--ignore-zerosr  z.ignore zero-filled blocks in the input tarball)r   r  r   r  )r   r  r   r   r  r  ZTARFILEz/input tar file. "-" to read from stdin instead.)[r   ArgumentParserr   r  r   partialdo_maincommand_helpr  r  r  r   r  r  r   r  r  ZRawDescriptionHelpFormatterr  r  Zadd_subparsersZ
add_parserr  r  r1   r  r5  r  r  r3  r  rS  r   r   r   ZSTDIN_MODE_DEFAULTr  r9   ZFILES_CACHE_MODE_UI_DEFAULTr7   rJ   r3   ZCHUNKER_PARAMSr!   r   r4  r:  rE  rH  r\  r0   re  rn  rl  ro  rr  rs  r}  r  FileTyperU  r{  r2   r>  rV  r  r  r  r   r#   r   rC  rG  r;  rL  r:   Z	keys_helpr  r  r<   r;   r  r  rF   r  r}  r  r  r  r  Z	REMAINDERr  )9r   r  r  r  r   Zcommon_parserZmid_common_parserZmount_epilog
subparsersZbenchmark_epilogr  Zbenchmark_parsersZbench_crud_epilogZbreak_lock_epilogZcheck_epilogZcompact_epilogZconfig_epilogr  Zcreate_epilogr  Zfs_groupZarchive_groupZdebug_epilogZdebug_parsersZdebug_info_epilogZdebug_dump_archive_items_epilogZdebug_dump_archive_epilogZdebug_dump_manifest_epilogZdebug_dump_repo_objs_epilogZdebug_search_repo_objs_epilogZdebug_id_hash_epilogZdebug_get_obj_epilogZdebug_put_obj_epilogZdebug_delete_obj_epilogZdebug_refcount_obj_epilogZdebug_dump_hints_epilogZdebug_convert_profile_epilogZdelete_epilogZdiff_epilogZexport_tar_epilogZextract_epilogZinfo_epilogZinit_epilogZkey_parsersZkey_export_epilogZkey_import_epilogZchange_passphrase_epilogZmigrate_to_repokey_epilogZlist_epilogZprune_epilogZrecreate_epilogZrename_epilogZserve_epilogZumount_epilogZupgrade_epilogZwith_lock_epilogZimport_tar_epilogr   )r  r  r  r  r   r   build_parserY  s^  
7

8
'r










 4


















































%













 
#

	
'
'+
+/0

7


4










c

#





zArchiver.build_parserc                 C   s   |  |dd }|dur[|j| jkr[t|}ttdd |}|  |dd }|j|jkr[h d}h d}t }|D ]}	|	|vsJJ d|	 t	||	|}
|
|urZt
||	|
 q>|S )zWusually, just returns argv, except if we deal with a ssh forced command for borg serve.r   Nc                 S   s   d| v S )N=r   )r  r   r   r   rD    s    z#Archiver.get_args.<locals>.<lambda>>   r   r   r  r  r  >   r  r   r  z*allowlist has denylisted attribute name %s)rT  r   r  r  r  r   	itertools	dropwhiler  r   r   )r   argvcmdr[  Zclient_argvZclient_resultZdenylistZ	allowlistZnot_present	attr_namer"  r   r   r   get_args  s    
zArchiver.get_argsc              	   C   s   |r|  |}|  }||pdg}|j| t|}|| jkr-|jr-|jr-|	d || jkrI|jsI|j
s;|jrA|	d n|jsI|	d t|ddsk| j| j| j| j| j| j| j| j| jh	}||vrktdt|dd ry|j|j|_|S )	Nr  z/Must not pass PATH with ``--paths-from-stdin``.zNo command given.z Need at least one PATH argument.r   Tz:Not allowed to bypass locking mechanism for chosen commandrJ   )r  r  rT  r  r  r   rS  r  r  r   r  r  r   r5  r3  r{  r>  rV  r  r  r  r  r-   r   Zwith_timestamprJ   )r   r   r   r   Zbypass_allowedr   r   r   rT  !  s.   


zArchiver.parse_argsc                 C   s   |st   t  t| d S r   )rR   rS   r   )r   r   is_server   r   r   prerun_checks;  s   zArchiver.prerun_checksc                 C   sJ   dddddd}|  D ]\}}||d}t||rdnd	 qd
S )zN turn on INFO level logging for args that imply that they will produce output r   borg.output.show-versionborg.output.show-rcr  zborg.output.progress)r   r  r  r  r   FINFOWARNN)r7  r   r  r  setLevel)r   r   Zoption_loggeroptionZlogger_nameZ
option_setr   r   r   _setup_implied_loggingB  s   zArchiver._setup_implied_loggingc                 C   s<   |j D ]}d|vrd| }td| t|d qdS )z9Turn on DEBUG level logging for specified --debug-topics.r(  zborg.debug.zEnabling debug topic %sDEBUGN)r  r   r  r  r  r  )r   r   r  r   r   r   _setup_topic_debuggingP  s   
zArchiver._setup_topic_debuggingc           	      C   s  t |j |j| _t|}|| jk}t|j||jd |j| _| j|O  _| 	t
| | | t|ddrGt|ddrGtd d|_|jrTtddt  | t| t sptd td	 td
 ttS t rxtt |jrdd l}dd l}td|j t |jd\}|! }t"t# }|$  z-t||W |%  |&  |j'dr|(|j| n	t)j*|j|dd W  d    S |%  |&  |j'dr|(|j| w t)j*|j|dd w 1 sw   Y  d S t||S )N)levelr  r   r  Fr  z;Ignoring --stats. It is not supported when using --dry-run.r  zborgbackup version %szYYou do not have a supported version of the msgpack python package installed. Terminating.zVThis should never happen as specific, supported versions are required by our setup.py.z-Do not contact borgbackup support about this.r   zWriting execution profile to %sr5  z.pyprofT)Zuse_bin_type)+rE  r  r   r   r  r
   r  r   r   r  varsr   r   r   r   r  r  r  r  r  r   r  rV   r   r/   r+   rU   PURE_PYTHON_MSGPACK_WARNINGr  cProfiler  r  r  ZProfiler{  localsenabledisableZsnapshot_statsendswithrF  rm   pack)	r   r   r   r  r$  r  rp  Zprofiler	variablesr   r   r   runX  sZ   









zArchiver.run)NNr   )Wr   r   r   r   r   r   r  staticmethodr
  r  r   r   r5  rN   r  r  r;  rC  rG  rL  r  r)  rS  r  r  r  ZREADr   rV  r>  r:  r{  r}  r  rU  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r3  r4  r   r:  rE  rH  r\  re  rl  rn  ro  rr  rs  r}  r  r  collectionsOrderedDictr  r  r  r  r  r  r  r  r  r  rT  r  r  r   r+  r   r   r   r   r      s   




&
&



P +9d
Y  0

V<


1 
aJ
*

F



	
|
	



1

7
B











 y:f~                 .
+r   c              
   C   s:  t | tj t|D ]n}|d |d j}}|dv rN|d }z|d  }|d j}W n ty:   d\}}Y nw t	
| dt| d	t|   n5|d
v rz|d j}z|d  }W n tyj   d}Y nw t	
| dt| d  nqW d   dS W d   dS W d   dS 1 sw   Y  dS )zLsearch the stack for infos about the currently processed file and print them   r   )r  r  r   rp  r  )r   r   ro  r  )r(  r   z/???N)rZ   signalSIG_IGNinspectgetouterframesf_localstellst_sizer   r   r  r>   r   )sig_nostackframer   locr   posr  r   r   r   sig_info_handler  s:   "
"r<  c                 C   s*   t dt jdd tjd t  d S )Nz)
Received SIGUSR2 at %s, dumping trace...r   )microsecondr   )r   r   nowr  r  r  faulthandlerZdump_traceback)r7  r8  r   r   r   sig_trace_handler  s   r@  c                  C   s  t tjjtjjdddt_t tjjtjjdddt_t  tdt	t
 tdt	tr tdt	tY tdtB tdt+ td	t t } d  } }}tj}z| tjtjd
}W n ty } z6| }|jrytjntj}t  dt  }t|tjd |tjkrt|tjd t|j W Y d }~nLd }~w t j!y } ztt"|tjd tt# W Y d }~n,d }~w t$y   d}t  dt  }t|tjd t|tjd tt# Y nw zt% | &|}W d    n	1 sw   Y  W n ty> } z&| }t'|j(}|jr$tjntj}t  dt  }|j}W Y d }~nd }~w t)j*y } z<|j+dvoO|j}|j+}|rYtjntj}|rc|j,}n| }d-dd |j. D }|dt  7 }t#}W Y d }~nld }~w t$y   d}d}tj}t  dt  }t#}Y nL t
y   d}tj}t  dt  }t/d }Y n0 ty   d}d}tj}t  dt  }t/d }Y n ty   d}d}t/d }Y nw |rt0j1||d |rt02|| |j3rUt4d}	d}
|t5kr|	6|
d|f  n9|t7kr+|	8|
d|f  n*|t#kr:|	1|
d|f  n|t/krI|	1|
d |f  n|	1|
d!|pQd"f  t| W d    n	1 sew   Y  W d    n	1 suw   Y  W d    n	1 sw   Y  W d    n	1 sw   Y  W d    n1 sw   Y  W d    d S W d    d S 1 sw   Y  d S )#Nr  T)line_bufferingSIGINTSIGHUPSIGTERMSIGUSR1SIGUSR2ZSIGINFOZSSH_ORIGINAL_COMMANDr  r   zLocal Exception)ZLockTimeoutc                 s   s    | ]}d | V  qdS )zBorg server: Nr   )r   lr   r   r   r     s    zmain.<locals>.<genexpr>r   zKeyboard interruptr   zReceived SIGTERMzSignal.SIGTERM   zReceived SIGHUP.zSignal.SIGHUPr   )r  r  z!terminating with %s status, rc %dsuccessr   r   r0  Zabnormali  )9r^   r  r  r  encodingr  r?  r&  rZ   r[   r  r\   r]   r<  r@  r   r  ERRORr  r  rE  r{  r   r-   Zget_message	tracebackr  
format_excrX   r   exitr   r   r   r   r+   r   rn   r+  r   r   r   ZRPCErrorZexception_classZexception_fullra  r  r,   r   r   logr  r  r)   r  r*   r   )archiverr   r  tbZtb_log_levelr   r  r   Z	importantZ	rc_loggerZexit_msgr   r   r   main  s   







   T rR  __main__)	FFFTFTFTN)r  rL  r   r-  r/  r?  r   r2  r  r   r  rE  r  r  rh  r0  r  r  r9  r  r   binasciir   r   
contextlibr   r   r   r  r   r   r	   r
   r  rF  r   r   Zalgorithms.checksumsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   	constantscompressr!   rW  r"   r#   r$   r%   r&   r'   Zcrypto.keymanagerr(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rq   Zhelpers.parseformatrr   rs   Znanorstrt   r  ru   rv   rw   rx   ry   r   rz   r{   r!  r|   r}   r~   r   r   Zremoter   r   r   r   r   r   r   r   r   r   Zupgraderr   r   BaseException	print_excrN  r  r#  r9  r,  r   TarFileZextraction_filterr   r   r   r   r   ZActionr   r   r<  r@  rR  r   r   r   r   r   <module>   s$   	
K                                       N
k
