#gitlab 연관된 merge request가 없는 commit을 org todo로 만들기
merge request는 org todo로 만들어서 잘 쓰고 있다. merge request 단위로는 계속 읽고 있는데, 아쉽게도 이게 다가 아니다. master에 직접 push도 허용하고 있어서 연관된 merge request가 없는 커밋(commit)도 있다. 주로 아티스트 커밋이지만 종종 프로그래머 커밋도 있다. 놓치면 안 되는 게 있어서 만들었다.
(defun commits-url (begin-date end-date page)
(let ((before (format "%sT00:00:00.000%%2B09:00" end-date))
(after (format "%sT00:00:00.000%%2B09:00" begin-date)))
(format "%s/repository/commits?page=%d&per_page=100&since=%s&until=%s&private_token=%s"
gitlab-api-base-url
page
after
before
gitlab-private-key)))
list repository commits API를 사용했다. merge request를 org todo로 만들 때는 하루에 100개가 넘는 일이 없어 대충 넘어갔는데, 커밋은 100개 넘는 일이 허다하다. 그래서 pagination 파라미터를 추가했다.
(defun commits (begin-date end-date)
(let ((id-titles '())
(json-array-type 'list)
(json-object-type 'plist)
(json-key-type 'keyword))
(dotimes (page 10) ;; 현명하게 그만둘 수 있는 방법이 있을텐데. 무식하게 10번 돈다 고고
(with-temp-buffer
(url-insert-file-contents (commits-url begin-date end-date (+ page 1)))
(let ((content (json-read)))
(dolist (commit content)
(add-to-list 'id-titles
(list :id
(plist-get commit :id)
:title
(plist-get commit :title)))))))
id-titles))
이제 보니 while 문 있네. 나중에 수정하지 뭐. 지금은 무식하게 10번 돈다. emacs에 property list 있는지 처음 알았다. json-object-type 변수에 ’plist를 바인딩하면 json-read 함수 리턴 값으로 property list를 리턴한다. key 타입도 바꿀 수 있다. 키워드 타입으로 변경.
(defun merge-request-url-from-commit (commit-id)
(format "%s/repository/commits/%s/merge_requests?private_token=%s"
gitlab-api-base-url
commit-id
gitlab-private-key))
(defun commits-without-merge-request (begin-date end-date)
(let ((ret '())
(json-array-type 'list)
(source-commits (commits begin-date end-date)))
(message (format "total commit count - %d" (length source-commits)))
(dolist (c source-commits)
(with-temp-buffer
(url-insert-file-contents (merge-request-url-from-commit (plist-get c :id)))
(let ((json-key-type 'string)
(content (json-read)))
(when (eq 0 (length content))
(add-to-list 'ret c)))))
ret))
commit 조회할 때, merge request id만이라도 있으면 좋으련만. 그런 거 없다. 그래서 commit을 순회하며 list merge requests associated with a commit API를 호출해서 merge request를 구한다. 비어있으면 연관된 merge request가 없는 거.
(defun insert-gitlab-commit-link (id)
(insert (format "[[%s/commit/%s][%s]]" gitlab-base-url id (substring id 0 10))))
(defun insert-gitlab-commits-without-mr-range ()
(interactive)
(let* ((begin-date (org-read-date))
(end-date (org-read-date))
(source-commits (commits-without-merge-request begin-date end-date)))
(dolist (c source-commits)
(insert "*** TODO ")
(insert-gitlab-commit-link (plist-get c :id))
(insert (format " %s" (plist-get c :title)))
(insert "\n"))))
merge request처럼 TODO 항목으로 추가한다. git commit id는 앞에서 10자 잘라서 표시.
C-x C-s C-x C-c