-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support gitlabs link headers to fetch all results #5
Comments
Have you thought about which route to go? Some if not most of the gitlab client libraries I've used has taken the path of I guess it would be better to have a synchronous version than nothing if that's faster to implement right now. This is the one issue that actually makes emacs-gitlab useless right now.. I'm not interested in my closed tickets from a few years ago which are the only ones I see now. |
This is probably something new in GitLab API.
This is why by default only first 20 projects/issues are on list. We should extend Question is how to solve this problem. Personally I don't use projects/isues list generated by emacs-gitlab. Thing is how to resolve UI and how to handle projects/milestones/issues. |
It's only the link headers that reveals where the last page is though without resorting to some trial and "error" method. It's the same for all paged api resources except one or two which they missed to add (might be fixed) |
Well, I don't understand what are you going to achieve. Could you please elaborate your workflow and what is the problem? |
All Gitlab API REST resource endpoints uses the link headers.. I don't understand what your comment about org files has any connection to this issue, however I am also only interested in the API side to eventually get my issues into git-commit-mode/auto-complete and org-mode. |
I thought that you are talking about lists generated by Currently it's not possible to see all projects with My comment about org files has this connection that you could use org-files to cache data from gitlab in nice format which can be parsed and filtered and you don't need to request gitlab every time. |
Alright.. |
There is no other way. Gitlab API returns 20 elements by default and you need to extend this limit to 100 and loop if it's not enough. There is an option to get all items however you need admin permissions on gitlab server. So, the only way to improve performance is to cache results. |
The alternative to always looping for all results is to introduce paging into the elisp gitlab API but I cannot see much reason for this.. I don't think there is much of a performance issue in fetching even up to 10 pages of json. |
This is why paging should be supported by emacs gitlab api. With helm you can see limited amount of results. So, you could use paging to limit amount of data you fetch from gitlab. Anyway I don't think that performance is a problem. Emacs gitlab api is based on |
I've just wrote some basic code to generate org tables for my issues in projects.. As a work aroynd I'm using this function to remove duplicates (defun my-gitlab-remove-duplicate-id (v)
"TODO"
(cl-remove-duplicates v
:test (lambda (x y)
(or (null y) (equal (assoc-default 'id x)
(assoc-default 'id y))))
:from-end t))
|
Unrelated to this issue but.. I did this last week, Just the bare minimun that I need to easy my working day.. It's a one way sync just running a function to update all open buffer with queries in the properties drawer.... I will try to make time to work a bit more on it and release it later on. At this time each property filter needs it's own function and filters only supports one entry so again, very basic. |
We definetly should coordinate our efforts. I have got function fetching all project data from gitlab to local copy of repo. Unfortunately I don't have time to finish this and debug properly. So, if we could prepare some nice org->gitlab interface together it could be great. I'll try to upload my code as additional library on next weekend. |
@thomasf great Org file ! |
Yeah.. what I have is currently only what I'm pasting below... I have never work with org mode directly in this way before so I am still learning how to do that properly.. A priority for me is to extract all check boxes from every issue as sub check boxes into the checkbox item tree. (require 'cl)
(require 'org)
(require 'gitlab)
(defun my-gitlab-remove-duplicate-id (v)
(remove-duplicates v
:test (lambda (x y)
(or (null y) (equal (assoc-default 'id x)
(assoc-default 'id y))))
:from-end t))
(defvar my-gitlab-projects-data nil)
(defun my-gitlab-projects ()
(unless my-gitlab-projects-data
(let ((p (gitlab-list-all-projects)) )
(setq
my-gitlab-projects-data
(append (my-gitlab-remove-duplicate-id p) nil))))
my-gitlab-projects-data)
(defun my-gitlab-project-by-id (project-id)
(--first
(equal project-id (assoc-default 'id it))
(my-gitlab-projects)))
(defun my-gitlab-project (path-with-namespace)
(--first
(equal path-with-namespace (assoc-default 'path_with_namespace it))
(my-gitlab-projects)))
(defun my-gitlab-project-id (project)
"TODO"
(assoc-default 'id project))
(defun my-gitlab-clear-cache ()
(interactive)
(setq my-gitlab-projects-data nil))
(defun my-gitlab-project-issues (project)
"TODO"
(my-gitlab-remove-duplicate-id
(gitlab-list-all-project-issues
(my-gitlab-project-id project))))
(defun my-gitlab-issues-filter-assignee (assignee issues)
(delq nil
(mapcar
#'(lambda (issue)
(when
(equal assignee
(assoc-default
'username
(or (assoc-default 'assignee issue)
'(username))))
issue))
issues)))
(defun my-gitlab-issues-filter-opened (issues)
(delq nil
(mapcar
#'(lambda (issue)
(when
(equal "opened"
(assoc-default 'state issue))
issue))
issues)))
(defun my-gitlab-issues-filter-milestone (iid issues)
(delq nil
(mapcar
#'(lambda (issue)
(let ((ms (assoc-default 'milestone issue)) )
(if (and ms (equal iid (assoc-default 'iid ms)))
issue
nil)))
issues)))
(defun my-gitlab-issues-org-update ()
(interactive)
(mapc #'(lambda (buffer)
(with-current-buffer buffer
(when
(eq major-mode 'org-mode)
(let ((case-fold-search nil))
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(while (re-search-forward
(concat "^[ \t]*:gitlab_issues:[ \t]+.*$")
nil t)
(save-restriction
(org-narrow-to-subtree)
(delete-region (org-end-of-meta-data-and-drawers) (org-end-of-subtree t t ))
(let* ((gitlab-project (org-entry-get-with-inheritance "gitlab_issues"))
(gitlab-assigned (org-entry-get-with-inheritance "gitlab_assigned"))
(gitlab-milestone (org-entry-get-with-inheritance "gitlab_milestone"))
(issues (my-gitlab-project-issues (my-gitlab-project gitlab-project))))
(when gitlab-assigned
(setq issues (my-gitlab-issues-filter-assignee gitlab-assigned issues)))
(when gitlab-milestone
(setq issues (my-gitlab-issues-filter-milestone (string-to-number gitlab-milestone) issues)))
(insert (my-gitlab-issues-org-tbl issues))
(org-update-checkbox-count)))
(org-end-of-subtree t t)
)))))))
(buffer-list)))
(defun my-gitlab-issues-org-tbl (issues)
(with-temp-buffer
(let ((in-subtree) )
(mapc
#'(lambda (issue)
(let* ((project (my-gitlab-project-by-id (assoc-default 'project_id issue)))
(project-nspath (assoc-default 'path_with_namespace project))
(issue-iid (assoc-default 'iid issue))
(issue-state (assoc-default 'state issue))
(issue-title (assoc-default 'title issue))
(issue-assignee (assoc-default
'username
(or (assoc-default 'assignee issue)
'(username ""))))
(issue-url (format "http://gitlab.hostname/%s/issues/%d" project-nspath issue-iid))
(issue-link (org-make-link-string issue-url (format "#%d" issue-iid))))
(insert
(cond
((string= issue-state "closed") "- [X] " )
((string= issue-state "opened") "- [ ] " ))
" "
;; (if (string= issue-state "opened") "TODO" "DONE")
issue-link
" "
issue-title
;; " "
;; (if (string= issue-state "opened") ":open:" ":closed:")
)
(end-of-line) (newline)
(when issue-assignee
(insert " ")
(insert "assigned: " issue-assignee)
(end-of-line) (newline))
(end-of-line) (newline)
))
issues))
(buffer-string)))
(provide 'my-gitlab)
|
For now, i juste create a file like that :
with this code : (require 'cl)
(require 'org)
(require 'gitlab)
(defun gitlab-issue-status-to-org (issue)
(cond ((string= (assoc-default 'state issue) "opened")
"TODO")
((string= (assoc-default 'state issue) "active")
"NEXT")
((string= (assoc-default 'state issue) "closed")
"DONE")
(t (assoc-default 'state issue))))
(defun gitlab-to-org ()
(interactive)
(with-temp-buffer
(mapc (lambda (project)
(insert "* " (assoc-default 'name project))
(end-of-line) (newline)
(insert "#+CATEGORY: Gitlab")
(end-of-line) (newline)
(mapc (lambda (milestone)
(insert "** " (assoc-default 'title milestone))
(end-of-line) (newline)
(mapc (lambda (issue)
(insert "*** "
(gitlab-issue-status-to-org issue)
" "
"[[gitlab:/"
(assoc-default 'path_with_namespace project)
"/issues/"
(number-to-string (assoc-default 'id issue))
"]["
(assoc-default 'title issue)
"]]")
(end-of-line) (newline)
(insert " DEADLINE: <"
(assoc-default 'due_date milestone)
">")
(end-of-line) (newline))
(gitlab-get-milestone-issues (assoc-default 'id project)
(assoc-default 'id milestone))))
(gitlab-list-project-milestones (assoc-default 'id project)))
(insert "** ALL")
(end-of-line) (newline)
(mapc (lambda (issue)
(unless (assoc-default 'milestone issue)
(insert "** "
(gitlab-issue-status-to-org issue)
" "
(assoc-default 'title issue))
(end-of-line) (newline)))
(gitlab-list-all-project-issues (assoc-default 'id project))))
(gitlab-list-projects))
(end-of-line) (newline)
(end-of-line) (newline)
(insert "#+LINK: gitlab " gitlab-host)
(buffer-string)))
|
The gitlab api has a http header named Link ( http://www.w3.org/wiki/LinkHeader ) which looks like this for a first result page:
If alot of requests might be required to reach a full result list emacs-gitlab should probably be converted to async/lexical scope first so that emacs doesn't freeze up while reqests are being fetched.
The text was updated successfully, but these errors were encountered: