;;; my-gitlab.el -- gitlab client -*- lexical-binding: t -*- ;; Copyright (C) 2023 Free Software Foundation. ;; Author: Yuchen Pei ;; Package-Requires: ((emacs "28.2")) ;; This file is part of dotfiles. ;; dotfiles is free software: you can redistribute it and/or modify it under ;; the terms of the GNU Affero General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; dotfiles is distributed in the hope that it will be useful, but WITHOUT ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General ;; Public License for more details. ;; You should have received a copy of the GNU Affero General Public ;; License along with dotfiles. If not, see . ;;; Commentary: ;; gitlab client. ;;; Code: (require 'infobox) (defun my-gitlab-get-project-id (url) (with-current-buffer (url-retrieve-synchronously (replace-regexp-in-string "\\.git$" "" url)) (let ((dom (libxml-parse-html-region (point-min) (point-max)))) (dom-attr (car (dom-search dom (lambda (n) (dom-attr n 'data-project-id)))) 'data-project-id)))) (defun my-gitlab-api-projects (url) (when-let* ((urlobj (url-generic-parse-url url)) (project-id (my-gitlab-get-project-id url))) (my-url-fetch-json (format "%s://%s/api/v4/projects/%s" (url-type urlobj) (url-host urlobj) project-id)))) (defvar my-gitlab-readme-get-raw nil "Whether to get raw or html readme") (defun my-gitlab-project-info (url) "Given a url, returns project info." (let ((info (my-gitlab-api-projects url))) (let-alist info (when .readme_url (setf (alist-get 'readme info) (if my-gitlab-readme-get-raw (format "\n%s" (my-url-fetch-raw (replace-regexp-in-string "/-/blob/" "/-/raw/" .readme_url))) (alist-get 'html (my-url-fetch-json (format "%s?format=json&viewer=rich" .readme_url))))))) info)) (defun my-gitlab-format-time-string (t) (format-time-string "%Y-%m-%d %M:%M:%S" (encode-time (parse-time-string t)))) (defun my-gitlab-project-url-p (url) (let ((urlobj (url-generic-parse-url url))) (and (equal (url-host urlobj) "gitlab.com") (string-match-p "^/[^/]+/[^/]+$" (url-filename urlobj))))) (require 'my-buffer) (defvar my-gitlab-project-info-specs `((http_url_to_repo . "Clone") (name_with_namespace . "Name") (description . "Description") (created_at . ("Created at" . my-gitlab-format-time-string)) (last_activity_at . ("Updated at" . my-gitlab-format-time-string)) (topics . ("Topics" . ,(lambda (xs) (mapconcat #'identity xs "; ")))) (star_count . ("Stars" . number-to-string)) (forks_count . ("Forks" . number-to-string)) (readme . (body . ,(lambda (text) (with-temp-buffer (insert text) (shr-render-region (point-min) (point-max)) (buffer-string))))))) (defun my-gitlab-project-infobox (url) "Display a gitlab project info at URL in a help buffer. A good example would be " (interactive "sGitlab project URL: ") (infobox-render (infobox-translate (my-gitlab-project-info url) my-gitlab-project-info-specs) `(my-gitlab-project-infobox ,url) (called-interactively-p 'interactive))) (defun my-grok-gitlab (url) (my-grok-gitlab-make-info (my-gitlab-api-projects url))) (defun my-grok-gitlab-make-info (raw) (list (cons "Title" (alist-get 'name raw)) (cons "Description" (my-clean-property-value (alist-get 'description raw))) (cons "Source" (alist-get 'web_url raw)) (cons "Subject" (string-join (alist-get 'tag_list raw) ", ")) (cons "Released" (substring (alist-get 'created_at raw) 0 10)) (cons "Last-activity" (substring (alist-get 'last_activity_at raw) 0 10)) (cons "Developers" (alist-get 'name (alist-get 'namespace raw))))) (provide 'my-gitlab) ;;; my-gitlab.el ends here