
    i0                        d 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 g dZ	g dZ
dZ ej                  d      Z ej                  d      Z ej                  d	      Z ej                  d
      Z ej                  d      Zh dZdedefdZdedefdZdedefdZdedefdZdededefdZdededefdZdedefdZdedededefdZ d Z!d Z"e#dk(  r e"        yy) u5  
extract-changed-files.py - 작업 보고서에서 변경 파일 목록 자동 추출

팀 작업 완료 보고서(markdown)에서 '생성/수정 파일 목록' 섹션을 파싱하여
project-map.py --incremental --changed-files에 전달 가능한 형식으로 출력합니다.

Usage:
    python3 extract-changed-files.py /path/to/report.md
    python3 extract-changed-files.py /path/to/report.md --project insuwiki --auto-update

출력 예시:
    {"changed_files": ["functions/src/crawlYoutubeChannels.ts", "functions/src/whisperStt.ts"], "deleted_files": []}
    N)Path)u)   ^#{1,4}\s+생성/수정\s*파일\s*목록u   ^#{1,4}\s+변경\s*파일u   ^#{1,4}\s+수정\s*파일u   ^#{1,4}\s+생성.*파일z^#{1,4}\s+Modified\s+Filesz^#{1,4}\s+Changed\s+Filesz^#{1,4}\s+Created.*Files)u   삭제zremoved?zdeleted?z
^#{1,4}\s+z^\|\s*([^|]+?)\s*\|(.+)$z/^[-*]\s+(`)?([^\s`|]+\.[a-zA-Z0-9_]+[^\s`]*)\1?z`([^`]+\.[a-zA-Z0-9_]+[^`]*)`uD   (?:^|[\s`|])([a-zA-Z0-9가-힣_./-]+\.[a-zA-Z0-9]{1,10})(?:[\s`|]|$)z^\|[-| :]+\|>   chgojsktmdpyrbrsshtscfgcppcssenvinijsxphpsqltsxtxtymlhtmljavajsonlocksassscsstomlyamlswifttype_strreturnc                     | sy| j                         j                         }t        D ])  }t        j                  ||t        j
                        s) y y)u<   변경 유형 문자열이 삭제를 나타내는지 확인.FT)striplowerDELETE_TYPE_PATTERNSresearch
IGNORECASE)r#   spats      4/home/jay/workspace/scripts/extract-changed-files.pyis_delete_actionr/   G   sH     A# 99S!R]]+     r,   c                 8   | j                         j                  d      j                         } | syd| vrd| vry| j                  dd      }t        |      dk(  r+|d   j                         j	                  d      }|t
        v ryd| v r| j                  d	      syy)
u5   문자열이 파일 경로처럼 보이는지 확인.`F./      )Thttp)r&   rsplitlenr'   rstripVALID_EXTENSIONS
startswith)r,   partsexts      r.   looks_like_file_pathr@   R   s    		""$A
!|1HHS!E
5zQAhnn%%c*""
axV,r0   c                     | j                         } | j                  d      } t        j                  dd|       j                         } | S )u=   경로 문자열 정리: 코드 스팬 제거, 공백 제거.r2   z	[,;:()]+$ )r&   r)   sub)r,   s    r.   
clean_pathrD   f   s:    		A	A
|R#))+AHr0   linesc                     t        |       D ];  \  }}t        D ]-  }t        j                  ||t        j                        s)|c c S  = y)uO   파일 목록 섹션의 시작 줄 인덱스를 찾는다. 없으면 -1 반환.)	enumerateSECTION_HEADER_PATTERNSr)   r*   r+   )rE   ilinepatterns       r.   find_section_startrM   p   sG    U# 4. 	Gyy$6	 r0   section_startc                    g }g }d}t        |dz   t        |             D ][  }| |   }t        j                  t        |      r||dz   kD  r ||fS d}t
        j                  |      rHt        j                  |      }|s`|j                  d      j                         }|j                  d      }	t        |      }
t        |
      s5t        j                  |      }|rt        |d         rt        |d         }
n|	j                  d      D cg c]#  }|j                         s|j                         % }}|r|d   nd}t        |      r|
|vs2|j                  |
       E|
|vsK|j                  |
       ^ ||fS c c}w )ua   
    테이블 형식에서 파일 목록 추출.
    반환: (changed_files, deleted_files)
    Fr5   Tr6   r   |rB   )ranger:   r)   matchNEXT_SECTION_PATTERNTABLE_SEPARATOR_PATTERNTABLE_ROW_PATTERNgroupr&   rD   r@   CODE_SPAN_PATTERNfindallsplitr/   append)rE   rN   changeddeleted
in_sectionrJ   rK   mraw_pathrestpath
code_spansr   	rest_cols
action_cols                  r.   extract_from_tablere   y   s   
 GG J=1$c%j1 ')Qx 88($/A8I4IH GE 
 #((. ##D)wwqz'')H771:D h'D'-.66x@
"6z!}"E%jm4D -1JJsOIqqwwyIII)21J
+w&NN4(w&NN4(O')R G Js   F#Fc                    g }g }t        |dz   t        |             D ]  }| |   }t        j                  t        |      r||dz   kD  r ||fS t
        j                  |      }|r;t        |j                  d            }t        |      r||vr|j                  |       t        j                  |      }|D ]/  }	t        |	      }
t        |
      s|
|vs|j                  |
       1  ||fS )ua   
    리스트 형식에서 파일 목록 추출.
    반환: (changed_files, deleted_files)
    r5   r6   )rQ   r:   r)   rR   rS   LIST_ITEM_PATTERNrD   rV   r@   rZ   rW   rX   )rE   rN   r[   r\   rJ   rK   r^   ra   rb   spanps              r.   extract_from_listrj      s    
 GG=1$c%j1 "Qx 88($/A8I4I$ G ##D)aggaj)D#D)w&NN4( '..t4
 	"D4 A#A&1G+;q!	"%". Gr0   report_pathc           	         t        |       }|j                         s	d|  g g dS 	 |j                  d      }|j                         }t        |      }|dk(  rXg }|D ]K  }t        j                  |      }|D ]/  }	t        |	      }
t        |
      s|
|vs|j                  |
       1 M |g ddS d	}t        |d
z   t        |dz   t        |                  D ]7  }t        j!                  ||         st"        j!                  ||         r5d} n |rt%        ||      \  }}nt'        ||      \  }}||dS # t        $ r}t	        |      g g dcY d}~S d}~ww xY w)u   
    보고서 파일 파싱하여 변경/삭제 파일 목록 반환.
    반환: {"changed_files": [...], "deleted_files": [...]}
    u   파일 없음: )errorchanged_filesdeleted_fileszutf-8)encodingNrG   u:   파일 목록 섹션을 찾지 못해 전체 파일 스캔)rn   ro   warningFr5   
   Trn   ro   )r   exists	read_textOSErrorstr
splitlinesrM   rW   rX   rD   r@   rZ   rQ   minr:   rU   rR   rT   re   rj   )rk   ra   contenterE   rN   r[   rK   spansrh   ri   	has_tablerJ   r\   s                 r.   parse_reportr~      s   
 D;;=*;-82`bccK..'.2  E 'u-M 	&D%--d3E &t$'*q/?NN1%&	& ")2  KG  H  	H I=1$c-"*<c%j&IJ ""58,5L5R5RSXYZS[5\I
 -e]C,UMB$w???  KQ"rJJKs   D7 7	E EEE
project_idresultc                 4   |j                  dg       }|j                  dg       }t        j                  j                  dt        t	        t
              j                         j                  j                              }| d| }| d| d}| d| d}| d	}	t	        |	      j                         sd
d|	 dS t	        |      j                         sd
d| dS t	        |      j                  j                  dd       t        j                  |	|d|dg}
|r|
ddj                  |      gz  }
|r|
ddj                  |      gz  }
t	        |      j                         r|
d|gz  }
	 t        j                  |
ddd      }|j                  dk(  rdnd
|j                  |j                   j#                         |j$                  j#                         dj                  |
      dS # t        j&                  $ r d
ddcY S t(        $ r}d
d| dcY d}~S d}~ww xY w)u[   
    --auto-update 옵션: project-map.py --incremental --changed-files 자동 실행.
    rn   ro   WORKSPACE_ROOTz
/projects/z/memory/project-maps/z.mdz/memory/drive-changes/z.jsonlz/scripts/project-map.pyrm   u   project-map.py 없음: )statusmessageu   프로젝트 경로 없음: T)parentsexist_okz--outputz--incrementalz--changed-files,z--deleted-filesz--drive-logx   )capture_outputtexttimeoutr   ok )r   
returncodestdoutstderrcmdu+   project-map.py 실행 타임아웃 (120초)u   project-map.py 실행 실패: N)getosenvironrw   r   __file__resolveparentrt   mkdirsys
executablejoin
subprocessrunr   r   r&   r   TimeoutExpiredrv   )rk   r   r   r[   r\   	workspaceproject_path
map_output	drive_logproject_map_scriptr   procr{   s                r.   run_auto_updater      s-    jj"-Gjj"-G

/T(^5K5K5M5T5T5[5[1\]I[
:,7L;3J<sCJ+3J<vFI%;&=>"#**,!0GHZG[.\]]$$&!0L\N.[\\ 	!!$!> 	JC !388G#455!388G#455Iy))T~~	
 #oo2d//kk'')kk'')88C=
 	
 $$ ]!.[\\ T!0Nqc.RSSTs%   (A:G# #H=HHHHc                      t        j                  d      } | j                  dd       | j                  dd d       | j                  d	d
dd       | j                         S )Nu9   작업 보고서에서 변경 파일 목록 자동 추출)descriptionrk   u   보고서 파일 경로 (.md))helpz	--projectu0   프로젝트 ID (--auto-update와 함께 사용))defaultr   z--auto-update
store_trueFu*   project-map.py --incremental 자동 실행)actionr   r   )argparseArgumentParseradd_argument
parse_args)parsers    r.   r   r   7  sy    $$OF ,KL
?  
 9	   r0   c                     t               } t        | j                        }| j                  r| j                  s]dd|j                  dg       |j                  dg       d}t        t        j                  |dd             t        j                  d	       t        | j                  | j                  |      }|j                  dg       |j                  dg       |d
}|j                  d      r|d   |d<   |j                  d      r`|d   |d<   nW|j                  dg       |j                  dg       d}|j                  d      r|d   |d<   |j                  d      r|d   |d<   t        t        j                  |dd             |j                  d      r(|j                  d      st        j                  d	       y y y )Nrm   u0   --auto-update 사용 시 --project 옵션 필수rn   ro   )r   r   rn   ro   Fr6   )ensure_asciiindentr5   )rn   ro   auto_updaterq   rs   )r   r~   rk   r   projectr   printr   dumpsr   exitr   )argsr   outputupdate_results       r.   mainr   J  s   <D $**+F||!M!'OR!@!'OR!@	F $**V%BCHHQK'(8(8$,,O#ZZ<#ZZ<(

 ::i  &y 1F9::g$WoF7O $ZZ<#ZZ<
 ::i  &y 1F9::g$WoF7O	$**V%
:;zz'6::o#> $?r0   __main__)$__doc__r   r   r   r)   r   r   pathlibr   rI   r(   rS   compilerU   rg   rW   FILE_PATH_PATTERNrT   r<   rw   boolr/   r@   rD   listintrM   tuplere   rj   dictr~   r   r   r   __name__ r0   r.   <module>r      s     	 	  
    %  BJJ:;  BJJQR  BJJ?@  BJJK 
 %"**_5  s t C D (# # d s 3d 33 35 3lT # % D*@c *@d *@Z6T 6T# 6Tt 6T 6Tr&(V zF r0   