docs: def file_transaction(work_dir, *rollback_files):
      """Wrap file generation in a transaction, moving to output if finishes.
      """
      exts = {".vcf": ".idx", ".bam": ".bai", "vcf.gz": ".tbi"}
      safe_fpaths, orig_names = _flatten_plus_safe(work_dir, rollback_files)
      __remove_files(safe_fpaths)  # remove any half-finished transactions
      try:
          if len(safe_fpaths) == 1:
              yield safe_fpaths[0]
          else:
              yield tuple(safe_fpaths)
      except:  # failure -- delete any temporary files
          __remove_files(safe_fpaths)
          raise
      else:  # worked -- move the temporary files to permanent location
          for safe, orig in zip(safe_fpaths, orig_names):
              if exists(safe):
                  shutil.move(safe, orig)
                  for check_ext, check_idx in exts.items():
                      if safe.endswith(check_ext):
                          safe_idx = safe + check_idx
                          if exists(safe_idx):
                              shutil.move(safe_idx, orig + check_idx)