|  | @@ -320,35 +320,31 @@ def check_all_source_directories_exist(source_directories):
 | 
	
		
			
				|  |  |          raise ValueError(f"Source directories do not exist: {', '.join(missing_directories)}")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -def create_archive(
 | 
	
		
			
				|  |  | +def make_base_create_command(
 | 
	
		
			
				|  |  |      dry_run,
 | 
	
		
			
				|  |  |      repository_path,
 | 
	
		
			
				|  |  |      config,
 | 
	
		
			
				|  |  |      config_paths,
 | 
	
		
			
				|  |  |      local_borg_version,
 | 
	
		
			
				|  |  |      global_arguments,
 | 
	
		
			
				|  |  | +    borgmatic_source_directories,
 | 
	
		
			
				|  |  |      local_path='borg',
 | 
	
		
			
				|  |  |      remote_path=None,
 | 
	
		
			
				|  |  |      progress=False,
 | 
	
		
			
				|  |  | -    stats=False,
 | 
	
		
			
				|  |  |      json=False,
 | 
	
		
			
				|  |  |      list_files=False,
 | 
	
		
			
				|  |  |      stream_processes=None,
 | 
	
		
			
				|  |  |  ):
 | 
	
		
			
				|  |  |      '''
 | 
	
		
			
				|  |  |      Given vebosity/dry-run flags, a local or remote repository path, a configuration dict, a
 | 
	
		
			
				|  |  | -    sequence of loaded configuration paths, the local Borg version, and global arguments as an
 | 
	
		
			
				|  |  | -    argparse.Namespace instance, create a Borg archive and return Borg's JSON output (if any).
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    If a sequence of stream processes is given (instances of subprocess.Popen), then execute the
 | 
	
		
			
				|  |  | -    create command while also triggering the given processes to produce output.
 | 
	
		
			
				|  |  | +    sequence of loaded configuration paths, the local Borg version, global arguments as an
 | 
	
		
			
				|  |  | +    argparse.Namespace instance, and a sequence of borgmatic source directories, return a tuple of
 | 
	
		
			
				|  |  | +    (base Borg create command flags, Borg create command positional arguments, open pattern file
 | 
	
		
			
				|  |  | +    handle, open exclude file handle).
 | 
	
		
			
				|  |  |      '''
 | 
	
		
			
				|  |  | -    borgmatic.logger.add_custom_log_levels()
 | 
	
		
			
				|  |  | -    borgmatic_source_directories = expand_directories(
 | 
	
		
			
				|  |  | -        collect_borgmatic_source_directories(config.get('borgmatic_source_directory'))
 | 
	
		
			
				|  |  | -    )
 | 
	
		
			
				|  |  |      if config.get('source_directories_must_exist', False):
 | 
	
		
			
				|  |  |          check_all_source_directories_exist(config.get('source_directories'))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      sources = deduplicate_directories(
 | 
	
		
			
				|  |  |          map_directories_to_devices(
 | 
	
		
			
				|  |  |              expand_directories(
 | 
	
	
		
			
				|  | @@ -364,11 +360,6 @@ def create_archive(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ensure_files_readable(config.get('patterns_from'), config.get('exclude_from'))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    try:
 | 
	
		
			
				|  |  | -        working_directory = os.path.expanduser(config.get('working_directory'))
 | 
	
		
			
				|  |  | -    except TypeError:
 | 
	
		
			
				|  |  | -        working_directory = None
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      pattern_file = (
 | 
	
		
			
				|  |  |          write_pattern_file(config.get('patterns'), sources)
 | 
	
		
			
				|  |  |          if config.get('patterns') or config.get('patterns_from')
 | 
	
	
		
			
				|  | @@ -451,6 +442,55 @@ def create_archive(
 | 
	
		
			
				|  |  |          repository_path, archive_name_format, local_borg_version
 | 
	
		
			
				|  |  |      ) + (sources if not pattern_file else ())
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    return (create_flags, create_positional_arguments, pattern_file, exclude_file)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def create_archive(
 | 
	
		
			
				|  |  | +    dry_run,
 | 
	
		
			
				|  |  | +    repository_path,
 | 
	
		
			
				|  |  | +    config,
 | 
	
		
			
				|  |  | +    config_paths,
 | 
	
		
			
				|  |  | +    local_borg_version,
 | 
	
		
			
				|  |  | +    global_arguments,
 | 
	
		
			
				|  |  | +    local_path='borg',
 | 
	
		
			
				|  |  | +    remote_path=None,
 | 
	
		
			
				|  |  | +    progress=False,
 | 
	
		
			
				|  |  | +    stats=False,
 | 
	
		
			
				|  |  | +    json=False,
 | 
	
		
			
				|  |  | +    list_files=False,
 | 
	
		
			
				|  |  | +    stream_processes=None,
 | 
	
		
			
				|  |  | +):
 | 
	
		
			
				|  |  | +    '''
 | 
	
		
			
				|  |  | +    Given vebosity/dry-run flags, a local or remote repository path, a configuration dict, a
 | 
	
		
			
				|  |  | +    sequence of loaded configuration paths, the local Borg version, and global arguments as an
 | 
	
		
			
				|  |  | +    argparse.Namespace instance, create a Borg archive and return Borg's JSON output (if any).
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    If a sequence of stream processes is given (instances of subprocess.Popen), then execute the
 | 
	
		
			
				|  |  | +    create command while also triggering the given processes to produce output.
 | 
	
		
			
				|  |  | +    '''
 | 
	
		
			
				|  |  | +    borgmatic.logger.add_custom_log_levels()
 | 
	
		
			
				|  |  | +    borgmatic_source_directories = expand_directories(
 | 
	
		
			
				|  |  | +        collect_borgmatic_source_directories(config.get('borgmatic_source_directory'))
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    (create_flags, create_positional_arguments, pattern_file, exclude_file) = (
 | 
	
		
			
				|  |  | +        make_base_create_command(
 | 
	
		
			
				|  |  | +            dry_run,
 | 
	
		
			
				|  |  | +            repository_path,
 | 
	
		
			
				|  |  | +            config,
 | 
	
		
			
				|  |  | +            config_paths,
 | 
	
		
			
				|  |  | +            local_borg_version,
 | 
	
		
			
				|  |  | +            global_arguments,
 | 
	
		
			
				|  |  | +            borgmatic_source_directories,
 | 
	
		
			
				|  |  | +            local_path,
 | 
	
		
			
				|  |  | +            remote_path,
 | 
	
		
			
				|  |  | +            progress,
 | 
	
		
			
				|  |  | +            json,
 | 
	
		
			
				|  |  | +            list_files,
 | 
	
		
			
				|  |  | +            stream_processes,
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      if json:
 | 
	
		
			
				|  |  |          output_log_level = None
 | 
	
		
			
				|  |  |      elif list_files or (stats and not dry_run):
 | 
	
	
		
			
				|  | @@ -462,6 +502,11 @@ def create_archive(
 | 
	
		
			
				|  |  |      # the terminal directly.
 | 
	
		
			
				|  |  |      output_file = DO_NOT_CAPTURE if progress else None
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    try:
 | 
	
		
			
				|  |  | +        working_directory = os.path.expanduser(config.get('working_directory'))
 | 
	
		
			
				|  |  | +    except TypeError:
 | 
	
		
			
				|  |  | +        working_directory = None
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      borg_environment = environment.make_environment(config)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # If database hooks are enabled (as indicated by streaming processes), exclude files that might
 |