레포지토리 폴더에 .git/hook/pre-commit 파일을 생성하여 아래 스크립트를 넣으면 커밋시에 README.md 파일에 트리가 자동으로 생성된다. (mac 기준)
.git/hook/readme-template.md도 만들어준다. __PROJECT_TREE__를 제외한 나머지부분은 꾸미고 싶은대로 바꿔도 된다.
추가: 위 명령어대로 했을때 뭔가 정렬이 이상하다 싶었는데, tree 옵션 문제였다.
마지막 수정 시간별로 파일을 정렬하는 -t 옵션을 없애고, 파일보다 디렉토리가 더 위로 오도록 하는 --dirsfirst를 사용하면 딱 예쁘게 정렬할 수 있다.
지난번에 이 레포지토리에 파일트리를 자동으로 생성하는 git hook을 만들었었다.
README에 파일 목록이 딱 보이니 어떤 내용들을 공부했었는지 파악하기도 쉽고, 깔끔해져서 정말 만족스러웠다.
그런데 문득, 이 레포지토리에 적은 글의 수 같은 정보를 함꼐 보여주면 더 좋지 않을까? 하는 생각이 들었다.
그래서 README와 git hook에 내용을 더 추가해보기로 했다! 일단 추가해본 부분은 파일(글)의 갯수, 폴더 갯수, 평균 글 길이이다. 파일 갯수는 내가 지금까지 몇가지의 내용을 공부했는지를 알 수 있고, 평균 글 길이는 얼마나 열심히 길게 적고있는지를 나타낼 수 있는 숫자이니 보고 (내가) 동기부여를 받을 수 있을 것 같아서 만들어보았다.
변경된 readme-template.md는 아래와 같다. backtic은 작은따옴표로 치환헀다.
pre-commit 코드는 파트별로 살펴보자.
이부분은 이전에도 있었듯이, tree 명령어 출력 결과를 링크가 달린 md 형식으로 변환해주는 코드이다. filepath 부분은 변수로 치환해서 공통으로 사용할 수 있도록 해줬다.
파일과 폴더의 숫자를 세는 것은 find와 wc 명령어를 사용했다. find 명령어로 각각 f, d 타입의 요소들을 리스트로 출력하면 wc -ㅣ로 행의 수를 세서 출력하는 형식이다. 그리고 깔끔한 출력을 위해 gsed로 공백과 줄바꿈을 없앴다.
글의 평균 길이를 측정하는 것도 find 명령어를 사용했다. 그 목록에 해당하는 글의 내용을 xargs cat이 받아서 전부 출력하면 wc 명령어가 글자 수를 세주는 구조이다. 파일 수가 점점 많아지면 이 과정에서의 메모리 부하가 심해지겠지만 아직 걱정할 수준은 아닌 것 같다. 현재는 내용이 총 50만 글자정도 되는데, 1억이 넘어가면 그떄부터 최적화를 생각해봐도 될 것 같다.
readme 파일을 생성하는 부분이다. 원래는 함수 호출 부분이 하나라서 밑부분에서 호출했었는데, 인자가 여러개가 되어서 그냥 이 함수에 다 합쳐줬다. cp로 템플릿 내용을 readme에 복사해놓고, 변수가 들어가야하는 부분을 하나씩 채워주는 흐름이다.
기존에는 템플릿에 변수를 대입한 내용을 만들어놓고 >를 사용해서 실제 readme 파일로 옮겨주었다. 근데 인자가 여러개가 되니까 하나를 대입해넣은 readme 파일에 또 덮어쓰기를 해야하는데, $readme > $readme와 같은 형식으로 코드를 작성하면 파일 내용이 자꾸 날아가서 명령어에 -i 옵션을 붙여서 readme 파일을 바로 수정하도록 변경했다.
이 부분이 함수를 호출하는 부분이고 매번 변경된 readme파일을 커밋하기가 좀 귀찮아져서 자동으로 전 커밋에 amend 해서 올라가도록 해줬다.
전 방식에선 해당 커밋이 아닌 바로 전 커밋에 amend 되어서 항상 force push를 해야하고 커밋 히스토리가 더러워진다는 단점이 있어서, git add만 하도록 수정도 해줬다.
전체 코드이다.
간단한 추가지만, 작업하는데 거의 3-4시간정도 걸린 것 같다…
bash나 perl 명령어에 대한 이해도가 낮아서 삽질을 정말 많이 했다. 다음에 git hook으로 만들고싶은게 또 생긴다면 그떄는 더 잘할 수 있지 않을까 기대해본다!
큰 변화는 아니지만 작게 수정할 요소가 있어 새 버전의 소스코드를 만들었다.
1. 줄바꿈 처리
이전에는 md에 줄바꿈을 적용하기 위해서 닫는 괄호인 ) 문자 뒤에 <br/>을 출력하도록 했는데, 파일명에 )가 들어가는 경우 불필요한 줄바꿈이 들어가서, <\/br>을 md link 형식으로 format을 바꿔주는 표현식 뒤에 붙였다.
둘을 별도의 표현식으로 분리하려다가, sed의 capture group에 대해서도 같이 찾아보게 되었다.
gsed로 string replace 하는 부분에 filepath 변수가 적용되어있지 않아 수정해주었다.
처음에는 그냥 따옴표에 $로 변수를 설정했는데 안되어서 구글링해보았더니 그 부분에서 따옴표와 쌍따옴표의 차이가 있다고 한다.
Single Quotes은 그냥 character를 그대로 인식하고, 쌍따옴표인 Double Quotes은 $, \, ! 등의 표현을 사용할 수 있다.
gnu 공식 문서에도 이러한 내용이 설명되어있다.
3.1.2.2 Single Quotes
Enclosing characters in single quotes (’) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
3.1.2.3 Double Quotes
Enclosing characters in double quotes (”) preserves the literal value of all characters within the quotes, with the exception of $, , \, and, when history expansion is enabled, !. The characters $ and retain their special meaning within double quotes (see Shell Expansions). The backslash retains its special meaning only when followed by one of the following characters: $, `, ”, , or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.
The special parameters * and @ have special meaning when in double quotes (see Shell Parameter Expansion).