
    (<i                    0   U d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	  ej                         dz  dz  Zd	ed
<    ed      Zd	ed<   dZded<   ddZddZddZddZddZ	 	 d	 	 	 	 	 	 	 d dZ	 	 	 	 	 	 d!dZ	 d"	 	 	 	 	 d#dZ	 	 d$	 	 	 	 	 	 	 d%dZy)&u  체크포인트(백업) 관리 유틸리티 (M-08).

타임스탬프 기반 백업 디렉토리에 파일 스냅샷을 저장하고 복원한다.
기본 저장 경로: ~/.hermes/checkpoints/ (없으면 /tmp/hermes_checkpoints/)
파일 이름 형식: {YYYYMMDD_HHMMSS_ffffff}__{label}__{original_filename}

Usage:
    from utils.checkpoint import snapshot, restore, list_checkpoints, cleanup_old
    path = snapshot("myfile.py", label="before_refactor")
    restore(path, "myfile.py")
    )annotations)datetime)Path)Union)atomic_text_writez.hermescheckpointsr   _DEFAULT_CHECKPOINT_DIRz/tmp/hermes_checkpoints_FALLBACK_CHECKPOINT_DIR__str_SEPc                     	 t         j                  dd       t         S # t        $ r  t        j                  dd       t        cY S w xY w)uJ   ~/.hermes/checkpoints/ 반환. 실패 시 /tmp/hermes_checkpoints/ 사용.Tparentsexist_ok)r	   mkdirOSErrorr
        A/home/jay/workspace/.worktrees/task-2057-dev2/utils/checkpoint.py_get_default_checkpoint_dirr      sH    (%%dT%B&& ( &&td&C''(s    &AAc                0    | t        |       S t               S )uK   checkpoint_dir 인수를 Path로 변환하고, None이면 기본값 반환.)r   r   checkpoint_dirs    r   _resolve_ckpt_dirr   $   s    #1#=4`C^C``r   c                    t        j                         j                  d      }|j                         r|j                         nd}| t         | t         | j
                   S )u?   형식: {YYYYMMDD_HHMMSS_ffffff}__{label}__{original_filename}.z%Y%m%d_%H%M%S_%fnolabel)r   nowstrftimestripr   name)original_pathlabelts
safe_labels       r   _make_backup_filenamer&   )   sP    		 	 !3	4B"'++-YJT$
|D6-*<*<)=>>r   c                `    | j                  t        d      }t        |      dk  ry|d   |d   fS )u?   파일명에서 (timestamp_str, label) 파싱. 실패 시 None.      Nr      )splitr   len)filenamepartss     r   _parse_backup_filenamer/   0   s3    NN4#E
5zA~8U1Xr   c                     || j                   z  S )u+   파일별 서브디렉토리 경로 반환.)r!   )	file_pathr   s     r   _get_file_subdirr2   8   s    INN**r   Nc                   t        |       }|j                         st        d|       t        |      }t	        ||      }|j                  dd       |t        ||      z  }t        ||j                  dd             |S )u  파일을 체크포인트에 백업한다.

    Args:
        file_path:      백업할 원본 파일 경로.
        label:          체크포인트 레이블 (선택).
        checkpoint_dir: 저장 디렉토리. None이면 기본 경로 사용.

    Returns:
        생성된 백업 파일 경로.

    Raises:
        FileNotFoundError: file_path가 존재하지 않을 때.
    u)   스냅샷 대상 파일이 없습니다: Tr   utf-8replaceencodingerrors)	r   existsFileNotFoundErrorr   r2   r   r&   r   	read_text)r1   r#   r   sourceckpt_dirsubdirbackup_paths          r   snapshotr@   =   s    $ )_F==?"KF8 TUU 0Hfh/F
LLL-0??Kk6#3#3WY#3#WXr   c                    t        |       }|j                         st        d|       t        t        |      |j	                  dd             y)u  체크포인트 파일을 대상 경로로 복원한다.

    Args:
        checkpoint_path: 복원할 체크포인트 파일 경로.
        target_path:     복원 대상 경로.

    Raises:
        FileNotFoundError: checkpoint_path가 존재하지 않을 때.
    u(   체크포인트 파일이 없습니다: r4   r5   r6   N)r   r9   r:   r   r;   )checkpoint_pathtarget_pathsrcs      r   restorerE   \   sG     
C::<"J3% PQQd;'PY)Z[r   c                Z   t        |       }t        |      }t        ||      }|j                         sg S g }|j	                         D ]M  }|j                         st        |j                        }|,|\  }}	|j                  ||	dk7  r|	nd||d       O |j                  d d       |S )uZ  특정 파일의 체크포인트 목록을 최신순으로 반환한다.

    Args:
        file_path:      원본 파일 경로 (파일명 기준으로 검색).
        checkpoint_dir: 저장 디렉토리. None이면 기본 경로 사용.

    Returns:
        dict 리스트 (최신순). 각 dict 키: path, label, timestamp, original_path
    r    )pathr#   	timestampr"   c                    t        | d         S )NrI   )r   )es    r   <lambda>z"list_checkpoints.<locals>.<lambda>   s    s1[>2 r   T)keyreverse)
r   r   r2   r9   iterdiris_filer/   r!   appendsort)
r1   r   r<   r=   r>   entriesbackup_fileparsedts_strr#   s
             r   list_checkpointsrW   o   s     )_F 0Hfh/F==?	')G~~' 
""$'(8(89>#"'9"4"#!'		

  LL2DLANr   c                    t        | |      }d}||d D ]-  }	 t        t        |d               j                          |dz  }/ |S # t        $ r Y =w xY w)u5  오래된 체크포인트를 정리한다.

    Args:
        file_path:      원본 파일 경로.
        keep:           유지할 최신 체크포인트 수 (기본 10).
        checkpoint_dir: 저장 디렉토리. None이면 기본 경로 사용.

    Returns:
        삭제된 체크포인트 수.
    r   r   NrH   r*   )rW   r   r   unlinkr   )r1   keepr   rS   deletedentrys         r   cleanup_oldr]      sm     yHGG 	U6]#$++-qLG N  		s   *A	AA)returnr   )r   Union[str, Path, None]r^   r   )r"   r   r#   r   r^   r   )r-   r   r^   ztuple[str, str] | None)r1   r   r   r   r^   r   )rG   N)r1   Union[str, Path]r#   r   r   r_   r^   r   )rB   r`   rC   r`   r^   None)N)r1   r`   r   r_   r^   zlist[dict[str, object]])
   N)r1   r`   rZ   intr   r_   r^   rc   )__doc__
__future__r   r   pathlibr   typingr   utils.atomic_writer   homer	   __annotations__r
   r   r   r   r&   r/   r2   r@   rE   rW   r]   r   r   r   <module>rk      s  
 #    0 )		i 7- G  G!%&?!@ $ @c (a
?+ -1 + 
	>\%\!\ 
\* .2&&*& &V -1
 + 		r   