1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Nit object oriented interface to [Github api](https://developer.github.com/v3/).
17 # This modules reifies Github API elements as Nit classes.
19 # For most use-cases you need to use the `GithubAPI` client.
22 intrude import json
::serialization_read
28 # Client to Github API
30 # To access the API you need an instance of a `GithubAPI` client.
33 # # Get Github authentification token.
34 # var token = get_github_oauth
35 # assert not token.is_empty
38 # var api = new GithubAPI(token)
41 # The API client allows you to get Github API entities.
44 # var repo = api.get_repo("nitlang/nit")
46 # assert repo.name == "nit"
48 # var user = api.get_user("Morriar")
50 # assert user.login == "Morriar"
54 # Github API OAuth token
56 # To access your private ressources, you must
57 # [authenticate](https://developer.github.com/guides/basics-of-authentication/).
59 # For client applications, Github recommands to use the
60 # [OAuth tokens](https://developer.github.com/v3/oauth/) authentification method.
64 # Be aware that there is [rate limits](https://developer.github.com/v3/rate_limit/)
65 # associated to the key.
66 var auth
: nullable String = null is optional
68 # User agent used for HTTP requests.
70 # Default is `nit_github_api`.
72 # See <https://developer.github.com/v3/#user-agent-required>
73 var user_agent
: String = "nit_github_api" is optional
75 # Headers to use on all requests
76 fun new_headers
: HeaderMap do
77 var map
= new HeaderMap
80 map
["Authorization"] = "token {auth}"
82 map
["User-Agent"] = user_agent
83 # FIXME remove when projects and team are no more in beta
84 map
["Accept"] = "application/vnd.github.inertia-preview+json"
85 map
["Accept"] = "application/vnd.github.hellcat-preview+json"
89 # Github API base url.
91 # Default is `https://api.github.com` and should not be changed.
92 var api_url
= "https://api.github.com"
94 # Send a HTTPRequest to the Github API
95 fun send
(method
, path
: String, headers
: nullable HeaderMap, body
: nullable String): nullable String do
97 path
= sanitize_uri
(path
)
98 var uri
= "{api_url}{path}"
99 var request
= new CurlHTTPRequest(uri
)
100 request
.method
= method
101 request
.user_agent
= user_agent
102 request
.headers
= headers
or else self.new_headers
104 return check_response
(uri
, request
.execute
)
107 private fun check_response
(uri
: String, response
: CurlResponse): nullable String do
108 if response
isa CurlResponseSuccess then
110 return response
.body_str
111 else if response
isa CurlResponseFailed then
112 last_error
= new GithubAPIError(
122 # Deserialize an object
123 fun deserialize
(string
: nullable Serializable): nullable Object do
124 if string
== null then return null
125 var deserializer
= new GithubDeserializer(string
.to_s
)
126 var res
= deserializer
.deserialize
127 if deserializer
.errors
.not_empty
then
129 last_error
= new GithubDeserializerErrors("Deserialization failed", deserializer
.errors
)
131 else if res
isa GithubError then
140 # Escape `uri` in an acceptable format for Github.
141 private fun sanitize_uri
(uri
: String): String do
142 # TODO better URI escape.
143 return uri
.replace
(" ", "%20")
146 # Last error occured during Github API communications.
147 var last_error
: nullable Error = null is public
writable
149 # Does the last request provoqued an error?
150 var was_error
= false is protected writable
152 # Execute a GET request on Github API.
154 # This method returns a deserialized result.
156 # For raw data see `send`.
159 # var api = new GithubAPI(get_github_oauth)
160 # var obj = api.get("/repos/nitlang/nit")
161 # assert obj isa Repo
162 # assert obj.name == "nit"
165 # Returns `null` in case of `error`.
168 # obj = api.get("/foo/bar/baz")
170 # assert api.was_error
171 # assert api.last_error isa GithubError
173 fun get
(path
: String, headers
: nullable HeaderMap, data
: nullable String): nullable Object do
174 return deserialize
(send
("GET", path
, headers
, data
))
177 # Get the Github logged user from `auth` token.
179 # Loads the `User` from the API or returns `null` if the user cannot be found.
182 # var api = new GithubAPI(get_github_oauth)
183 # var user = api.get_auth_user
184 # assert user.login == "Morriar"
186 fun get_auth_user
: nullable User do
187 return get
("/user").as(nullable User)
190 # Get the Github user with `login`
192 # Loads the `User` from the API or returns `null` if the user cannot be found.
195 # var api = new GithubAPI(get_github_oauth)
196 # var user = api.get_user("Morriar")
197 # print user or else "null"
198 # assert user.login == "Morriar"
200 fun get_user
(login
: String): nullable User do
201 return get
("/users/{login}").as(nullable User)
204 # Get the Github repo with `full_name`.
206 # Loads the `Repo` from the API or returns `null` if the repo cannot be found.
209 # var api = new GithubAPI(get_github_oauth)
210 # var repo = api.get_repo("nitlang/nit")
211 # assert repo.name == "nit"
212 # assert repo.owner.login == "nitlang"
213 # assert repo.default_branch == "master"
215 fun get_repo
(repo_slug
: String): nullable Repo do
216 return get
("/repos/{repo_slug}").as(nullable Repo)
219 # List of repo branches.
222 # * `page`: page to fetch (default: 1)
223 # * `per_page`: number of branches by page (default: 30)
224 fun get_repo_branches
(repo_slug
: String, page
, per_page
: nullable Int): Array[Branch] do
225 return new GithubArray[Branch].from
(get
(
226 "/repos/{repo_slug}/branches?{pagination(page, per_page)}"))
229 # List of issues associated with their ids.
230 fun get_repo_issues
(repo_slug
: String, page
, per_page
: nullable Int): Array[Issue] do
231 return new GithubArray[Issue].from
(get
(
232 "/repos/{repo_slug}/issues?{pagination(page, per_page)}"))
235 # Search issues in this repo form an advanced query.
240 # var issues = repo.search_issues("is:open label:need_review")
243 # See <https://developer.github.com/v3/search/#search-issues>.
244 fun search_repo_issues
(repo_slug
: String, query
: String, page
, per_page
: nullable Int): nullable SearchResults do
245 return get
("/search/issues?q={query} repo:{repo_slug}&{pagination(page, per_page)}").as(nullable SearchResults)
248 # List of labels associated with their names.
249 fun get_repo_labels
(repo_slug
: String, page
, per_page
: nullable Int): Array[Label] do
250 return new GithubArray[Label].from
(get
(
251 "/repos/{repo_slug}/labels?{pagination(page, per_page)}"))
254 # List of milestones associated with their ids.
255 fun get_repo_milestones
(repo_slug
: String, page
, per_page
: nullable Int): Array[Milestone] do
256 return new GithubArray[Milestone].from
(get
(
257 "/repos/{repo_slug}/milestones?{pagination(page, per_page)}"))
260 # List of pull-requests associated with their ids.
262 # Implementation notes: because PR numbers are not consecutive,
263 # PR are loaded from pages.
264 # See: https://developer.github.com/v3/pulls/#list-pull-requests
265 fun get_repo_pulls
(repo_slug
: String, page
, per_page
: nullable Int): Array[PullRequest] do
266 return new GithubArray[PullRequest].from
(get
(
267 "/repos/{repo_slug}/pulls?{pagination(page, per_page)}"))
270 # List of contributor related statistics.
271 fun get_repo_contrib_stats
(repo_slug
: String): Array[ContributorStats] do
272 return new GithubArray[ContributorStats].from
(get
("/repos/{repo_slug}/stats/contributors"))
275 # Get the Github branch with `name`.
277 # Returns `null` if the branch cannot be found.
280 # var api = new GithubAPI(get_github_oauth)
281 # var repo = api.get_repo("nitlang/nit")
282 # assert repo != null
283 # var branch = api.get_branch(repo, "master")
284 # assert branch.name == "master"
285 # assert branch.commit isa Commit
287 fun get_branch
(repo_slug
: String, name
: String): nullable Branch do
288 return get
("/repos/{repo_slug}/branches/{name}").as(nullable Branch)
291 # Get the Github commit with `sha`.
293 # Returns `null` if the commit cannot be found.
296 # var api = new GithubAPI(get_github_oauth)
297 # var repo = api.get_repo("nitlang/nit")
298 # assert repo != null
299 # var commit = api.get_commit(repo, "64ce1f")
300 # assert commit isa Commit
302 fun get_commit
(repo_slug
: String, sha
: String): nullable Commit do
303 return get
("/repos/{repo_slug}/commits/{sha}").as(nullable Commit)
306 # Get the status of a commit
308 # The status holds the result of each check ran on a commit like CI, reviews etc.
309 fun get_commit_status
(repo_slug
: String, sha
: String): nullable CommitStatus do
310 return get
("/repos/{repo_slug}/commits/{sha}/status").as(nullable CommitStatus)
313 # Get the Github issue #`number`.
315 # Returns `null` if the issue cannot be found.
318 # var api = new GithubAPI(get_github_oauth)
319 # var repo = api.get_repo("nitlang/nit")
320 # assert repo != null
321 # var issue = api.get_issue(repo, 1)
322 # assert issue.title == "Doc"
324 fun get_issue
(repo_slug
: String, number
: Int): nullable Issue do
325 return get
("/repos/{repo_slug}/issues/{number}").as(nullable Issue)
328 # List of event on this issue.
329 fun get_issue_comments
(repo_slug
: String, issue_number
: Int, page
, per_page
: nullable Int): Array[IssueComment] do
330 return new GithubArray[IssueComment].from
(get
(
331 "/repos/{repo_slug}/issues/{issue_number}/comments?{pagination(page, per_page)}"))
334 # List of events on this issue.
335 fun get_issue_events
(repo_slug
: String, issue_number
: Int, page
, per_page
: nullable Int): Array[IssueEvent] do
336 return new GithubArray[IssueEvent].from
(get
(
337 "/repos/{repo_slug}/issues/{issue_number}/events?{pagination(page, per_page)}"))
340 # Get the Github pull request #`number`.
342 # Returns `null` if the pull request cannot be found.
345 # var api = new GithubAPI(get_github_oauth)
346 # var repo = api.get_repo("nitlang/nit")
347 # assert repo != null
348 # var pull = api.get_pull(repo, 1)
349 # assert pull.title == "Doc"
350 # assert pull.user.login == "Morriar"
352 fun get_pull
(repo_slug
: String, number
: Int): nullable PullRequest do
353 return get
("/repos/{repo_slug}/pulls/{number}").as(nullable PullRequest)
356 # List of comments on a pull request
357 fun get_pull_comments
(repo_slug
: String, pull_number
: Int, page
, per_page
: nullable Int): Array[PullComment] do
358 return new GithubArray[PullComment].from
(get
(
359 "/repos/{repo_slug}/pulls/{pull_number}/comments?{pagination(page, per_page)}"))
362 # Get a specific pull request comment
363 fun get_pull_comment
(repo_slug
: String, id
: Int): nullable PullComment do
364 return get
("/repos/{repo_slug}/pulls/comments/{id}").as(nullable PullComment)
367 # Get the Github label with `name`.
369 # Returns `null` if the label cannot be found.
372 # var api = new GithubAPI(get_github_oauth)
373 # var repo = api.get_repo("nitlang/nit")
374 # assert repo != null
375 # var labl = api.get_label(repo, "ok_will_merge")
376 # assert labl != null
378 fun get_label
(repo_slug
: String, name
: String): nullable Label do
379 return get
("/repos/{repo_slug}/labels/{name}").as(nullable Label)
382 # Get the Github milestone with `id`.
384 # Returns `null` if the milestone cannot be found.
387 # var api = new GithubAPI(get_github_oauth)
388 # var repo = api.get_repo("nitlang/nit")
389 # assert repo != null
390 # var stone = api.get_milestone(repo, 4)
391 # assert stone.title == "v1.0prealpha"
393 fun get_milestone
(repo_slug
: String, id
: Int): nullable Milestone do
394 return get
("/repos/{repo_slug}/milestones/{id}").as(nullable Milestone)
397 # Get the Github issue event with `id`.
399 # Returns `null` if the event cannot be found.
402 # var api = new GithubAPI(get_github_oauth)
403 # var repo = api.get_repo("nitlang/nit")
404 # assert repo isa Repo
405 # var event = api.get_issue_event(repo, 199674194)
406 # assert event isa IssueEvent
407 # assert event.actor.login == "privat"
408 # assert event.event == "labeled"
409 # assert event.labl isa Label
410 # assert event.labl.name == "need_review"
412 fun get_issue_event
(repo_slug
: String, id
: Int): nullable IssueEvent do
413 return get
("/repos/{repo_slug}/issues/events/{id}").as(nullable IssueEvent)
416 # Get the Github commit comment with `id`.
418 # Returns `null` if the comment cannot be found.
421 # var api = new GithubAPI(get_github_oauth)
422 # var repo = api.get_repo("nitlang/nit")
423 # assert repo != null
424 # var comment = api.get_commit_comment(repo, 8982707)
425 # assert comment.user.login == "Morriar"
426 # assert comment.body == "For testing purposes...\n"
427 # assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
429 fun get_commit_comment
(repo_slug
: String, id
: Int): nullable CommitComment do
430 return get
("/repos/{repo_slug}/comments/{id}").as(nullable CommitComment)
433 # Get the Github issue comment with `id`.
435 # Returns `null` if the comment cannot be found.
438 # var api = new GithubAPI(get_github_oauth)
439 # var repo = api.get_repo("nitlang/nit")
440 # assert repo != null
441 # var comment = api.get_issue_comment(repo, 6020149)
442 # assert comment.user.login == "privat"
443 # assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
444 # assert comment.issue_number == 10
446 fun get_issue_comment
(repo_slug
: String, id
: Int): nullable IssueComment do
447 return get
("/repos/{repo_slug}/issues/comments/{id}").as(nullable IssueComment)
450 private fun pagination
(page
, per_page
: nullable Int): String do
451 return "page={page or else 1}&per_page={per_page or else 30}"
455 # Return deserialization as an array of E
457 # Non-subtypes will be ignored.
458 private class GithubArray[E
]
461 # Create `self` from an Array of objects
463 # Objects non-subtyping E will be ignored.
464 init from
(res
: nullable Object) do
465 if not res
isa Array[Object] then return
467 if obj
isa E
then add obj
472 # An Error returned by GithubAPI
477 # An Error returned by https://api.github.com
479 # Anything that can occurs when sending request to the API:
480 # * Can't connect to API
481 # * Ressource not found
487 # Status code obtained
490 # URI that returned the error
491 var requested_uri
: String
494 # An Error returned while deserializing objects from the API
495 class GithubDeserializerErrors
498 # Errors returned by the deserizalization process
499 var deserizalization_errors
: Array[Error]
504 # Provides access to [Github user data](https://developer.github.com/v3/users/).
505 # Should be accessed from `GithubAPI::get_user`.
511 var login
: String is writable
513 # Avatar image url for this user.
514 var avatar_url
: nullable String is writable
516 # User public name if any.
517 var name
: nullable String is writable
519 # User public email if any.
520 var email
: nullable String is writable
522 # User public blog if any.
523 var blog
: nullable String is writable
526 # A Github repository.
528 # Provides access to [Github repo data](https://developer.github.com/v3/repos/).
529 # Should be accessed from `GithubAPI::get_repo`.
533 # Repo full name on Github.
534 var full_name
: String is writable
536 # Repo short name on Github.
537 var name
: String is writable
539 # Get the repo owner.
540 var owner
: User is writable
542 # Repo default branch name.
543 var default_branch
: nullable String = null is optional
, writable
548 # Should be accessed from `GithubAPI::get_branch`.
550 # See <https://developer.github.com/v3/repos/#list-branches>.
555 var name
: String is writable
557 # Get the last commit of `self`.
558 var commit
: Commit is writable
563 # Should be accessed from `GithubAPI::get_commit`.
565 # See <https://developer.github.com/v3/repos/commits/>.
570 var sha
: String is writable
572 # Parent commits of `self`.
573 var parents
: nullable Array[Commit] = null is writable
575 # Author of the commit.
576 var author
: nullable GitUser is writable
578 # Committer of the commit.
579 var committer
: nullable GitUser is writable
581 # Authoring date as String.
582 var author_date
: nullable String is writable
584 # Commit date as String.
585 var commit_date
: nullable String is writable
587 # List files staged in this commit.
588 var files
: nullable Array[GithubFile] = null is optional
, writable
591 var message
: nullable String is writable
593 # Git commit representation linked to this commit.
594 var commit
: nullable GitCommit
597 # A Git Commit representation
602 var sha
: nullable String is writable
604 # Parent commits of `self`.
605 var parents
: nullable Array[GitCommit] = null is writable
607 # Author of the commit.
608 var author
: nullable GitUser is writable
610 # Committer of the commit.
611 var committer
: nullable GitUser is writable
614 var message
: nullable String is writable
617 # Git user authoring data
622 var date
: nullable String = null is writable
627 # Should be accessed from `GithubAPI::get_issue`.
629 # See <https://developer.github.com/v3/issues/>.
634 var number
: Int is writable
637 var id
: nullable Int is writable
640 var title
: String is writable
642 # User that created this issue.
643 var user
: nullable User is writable
645 # List of labels on this issue associated to their names.
646 var labels
: nullable Array[Label] is writable
648 # State of the issue on Github.
649 var state
: String is writable
651 # Is the issue locked?
652 var locked
: nullable Bool is writable
654 # Assigned `User` (if any).
655 var assignee
: nullable User is writable
657 # `Milestone` (if any).
658 var milestone
: nullable Milestone is writable
660 # Number of comments on this issue.
661 var comments
: nullable Int is writable
663 # Creation time as String.
664 var created_at
: String is writable
666 # Last update time as String (if any).
667 var updated_at
: nullable String is writable
669 # Close time as String (if any).
670 var closed_at
: nullable String is writable
672 # Full description of the issue.
673 var body
: nullable String is writable
675 # User that closed this issue (if any).
676 var closed_by
: nullable User is writable
678 # Is this issue linked to a pull request?
679 var is_pull_request
: Bool = false is writable
682 # A Github pull request.
684 # Should be accessed from `GithubAPI::get_pull`.
686 # PullRequest are basically Issues with more data.
687 # See <https://developer.github.com/v3/pulls/>.
692 # Merge time as String (if any).
693 var merged_at
: nullable String is writable
696 var merge_commit_sha
: nullable String is writable
698 # Count of comments made on the pull request diff.
699 var review_comments
: nullable Int is writable
701 # Pull request head (can be a commit SHA or a branch name).
702 var head
: PullRef is writable
704 # Pull request base (can be a commit SHA or a branch name).
705 var base
: PullRef is writable
707 # Is this pull request merged?
708 var merged
: nullable Bool is writable
710 # Is this pull request mergeable?
711 var mergeable
: nullable Bool is writable
713 # Mergeable state of this pull request.
715 # See <https://developer.github.com/v3/pulls/#list-pull-requests>.
716 var mergeable_state
: nullable String is writable
718 # User that merged this pull request (if any).
719 var merged_by
: nullable User is writable
721 # Count of commits in this pull request.
722 var commits
: nullable Int is writable
725 var additions
: nullable Int is writable
727 # Deleted line count.
728 var deletions
: nullable Int is writable
730 # Changed files count.
731 var changed_files
: nullable Int is writable
734 var patch_url
: nullable String is writable
737 # A pull request reference (used for head and base).
741 # Label pointed by `self`.
742 var labl
: String is writable, serialize_as
("label")
744 # Reference pointed by `self`.
745 var ref
: String is writable
747 # Commit SHA pointed by `self`.
748 var sha
: String is writable
750 # User pointed by `self`.
751 var user
: User is writable
753 # Repo pointed by `self` (if any).
755 # A `null` value means the `repo` was deleted.
756 var repo
: nullable Repo is writable
761 # Should be accessed from `GithubAPI::get_label`.
763 # See <https://developer.github.com/v3/issues/labels/>.
768 var name
: String is writable
771 var color
: String is writable
774 # A Github milestone.
776 # Should be accessed from `GithubAPI::get_milestone`.
778 # See <https://developer.github.com/v3/issues/milestones/>.
782 # The milestone id on Github.
783 var number
: nullable Int = null is writable
786 var title
: String is writable
788 # Milestone long description.
789 var description
: nullable String is writable
791 # Count of opened issues linked to this milestone.
792 var open_issues
: nullable Int = null is writable
794 # Count of closed issues linked to this milestone.
795 var closed_issues
: nullable Int = null is writable
798 var state
: nullable String is writable
800 # Creation time as String.
801 var created_at
: nullable String is writable
803 # User that created this milestone.
804 var creator
: nullable User is writable
806 # Due time as String (if any).
807 var due_on
: nullable String is writable
809 # Last update time as String (if any).
810 var updated_at
: nullable String is writable
812 # Close time as String (if any).
813 var closed_at
: nullable String is writable
818 # There is two kinds of comments:
820 # * `CommitComment` are made on a commit page.
821 # * `IssueComment` are made on an issue or pull request page.
822 # * `PullComment` are made on the diff associated to a pull request.
823 abstract class Comment
826 # Identifier of this comment.
827 var id
: Int is writable
829 # User that made this comment.
830 var user
: User is writable
832 # Creation time as String.
833 var created_at
: String is writable
835 # Last update time as String (if any).
836 var updated_at
: nullable String is writable
839 var body
: String is writable
841 # Does the comment contain an acknowledgement (+1)
843 return body
.has
("\\+1\\b".to_re
) or body
.has
(":+1:") or body
.has
(":shipit:")
847 # A comment made on a commit.
853 var commit_id
: String is writable
855 # Position of the comment on the line.
856 var position
: nullable Int is writable
858 # Line of the comment.
859 var line
: nullable Int is writable
861 # Path of the commented file.
862 var path
: nullable String is writable
867 # Can contain sub-status for reviews, CI etc.
871 # Global state of this commit
872 var state
: nullable String = null is optional
, writable
874 # Sha of the commit this status is for
875 var sha
: nullable String = null is optional
, writable
877 # Repository the commit belongs to
878 var repository
: nullable Repo = null is optional
, writable
880 # All sub statuses (one for each check)
881 var statuses
= new Array[RepoStatus] is optional
, writable
883 # Total count of sub statuses
884 var total_count
: nullable Int = null is optional
, writable
887 # Sub status of a CommitStatus
889 # Represents a check applied to a commit (reviews, CI, ...).
893 # State of this check
894 var state
: nullable String = null is optional
, writable
896 # Description of this check
897 var description
: nullable String = null is optional
, writable
900 var target_url
: nullable String = null is optional
, writable
902 # Context this status is related to
904 # Used to hold the name of the check applied.
905 var context
: nullable String = null is optional
, writable
907 # Date when this status was created
908 var created_at
: nullable String = null is optional
, writable
910 # Last date this status was updated
911 var updated_at
: nullable String = null is optional
, writable
914 # Comments made on Github issue and pull request pages.
916 # Should be accessed from `GithubAPI::get_issue_comment`.
918 # See <https://developer.github.com/v3/issues/comments/>.
923 # Issue that contains `self`.
924 fun issue_number
: Int do return issue_url
.split
("/").last
.to_i
926 # Link to the issue document on API.
927 var issue_url
: String is writable
930 # Comments made on Github pull request diffs.
932 # Should be accessed from `GithubAPI::get_diff_comment`.
934 # See <https://developer.github.com/v3/pulls/comments/>.
939 # Pull request that contains `self`.
940 fun pull_number
: Int do return pull_request_url
.split
("/").last
.to_i
942 # Link to the pull request on API.
943 var pull_request_url
: String is writable
946 var diff_hunk
: String is writable
948 # Path of commented file.
949 var path
: String is writable
951 # Position of the comment on the file.
952 var position
: nullable Int is writable
954 # Original position in the diff.
955 var original_position
: Int is writable
957 # Commit referenced by this comment.
958 var commit_id
: String is writable
960 # Original commit id.
961 var original_commit_id
: String is writable
964 # An event that occurs on a Github `Issue`.
966 # Should be accessed from `GithubAPI::get_issue_event`.
968 # See <https://developer.github.com/v3/issues/events/>.
972 # Event id on Github.
973 var id
: Int is writable
975 # User that initiated the event.
976 var actor
: User is writable
978 # Creation time as String.
979 var created_at
: String is writable
982 var event
: String is writable
984 # Commit linked to this event (if any).
985 var commit_id
: nullable String is writable
987 # Label linked to this event (if any).
988 var labl
: nullable Label is writable, serialize_as
("label")
990 # User linked to this event (if any).
991 var assignee
: nullable User is writable
993 # Milestone linked to this event (if any).
994 var milestone
: nullable Milestone is writable
996 # Rename linked to this event (if any).
997 var rename
: nullable RenameAction is writable
1000 # A rename action maintains the name before and after a renaming action.
1004 # Name before renaming.
1005 var from
: String is writable
1007 # Name after renaming.
1008 var to
: String is writable
1012 # Should be accessed from `Repo::contrib_stats`.
1014 # See <https://developer.github.com/v3/repos/statistics/>.
1015 class ContributorStats
1019 redef type OTHER: ContributorStats
1021 # User these statistics are about.
1022 var author
: User is writable
1024 # Total number of commit.
1025 var total
: Int is writable
1027 # Array of weeks of activity with detailed statistics.
1028 var weeks
: Array[ContributorWeek] is writable
1030 # ContributorStats can be compared on the total amount of commits.
1031 redef fun <(o
) do return total
< o
.total
1034 # Contributor stats weekly hash
1035 class ContributorWeek
1038 # Start of week given a Unix timestamp
1041 # Number of additions
1044 # Number of deletions
1051 # A Github file representation.
1053 # Mostly a wrapper around a json object.
1058 var filename
: String is writable
1061 # A list of results returned buy `/search`
1065 # Total count with other pages
1066 var total_count
: Int
1068 # Does this page contain all the results?
1069 var incomplete_results
: Bool
1071 # Results in this page
1072 var items
: Array[Object]
1075 # JsonDeserializer specific for Github objects.
1076 class GithubDeserializer
1077 super JsonDeserializer
1079 private var pattern_base
= "https://api.github.com"
1081 # Url patterns to class names
1082 var url_patterns
: Map[Regex, String] is lazy
do
1083 var map
= new HashMap[Regex, String]
1084 map
["{pattern_base}/users/[^/]*$".to_re
] = "User"
1085 map
["{pattern_base}/repos/[^/]*/[^/]*$".to_re
] = "Repo"
1086 map
["{pattern_base}/repos/[^/]*/[^/]*/labels/[^/]+$".to_re
] = "Label"
1087 map
["{pattern_base}/repos/[^/]*/[^/]*/milestones/[0-9]+$".to_re
] = "Milestone"
1088 map
["{pattern_base}/repos/[^/]*/[^/]*/issues/[0-9]+$".to_re
] = "Issue"
1089 map
["{pattern_base}/repos/[^/]*/[^/]*/issues/comments/[0-9]+$".to_re
] = "IssueComment"
1090 map
["{pattern_base}/repos/[^/]*/[^/]*/issues/events/[0-9]+$".to_re
] = "IssueEvent"
1091 map
["{pattern_base}/repos/[^/]*/[^/]*/pulls/[0-9]+$".to_re
] = "PullRequest"
1092 map
["{pattern_base}/repos/[^/]*/[^/]*/pulls/comments/[0-9]+$".to_re
] = "PullComment"
1093 map
["{pattern_base}/repos/[^/]*/[^/]*/comments/[0-9]+$".to_re
] = "CommitComment"
1094 map
["{pattern_base}/repos/[^/]*/[^/]*/commits/[a-f0-9]+$".to_re
] = "Commit"
1095 map
["{pattern_base}/repos/[^/]*/[^/]*/commits/[a-f0-9]+/status$".to_re
] = "CommitStatus"
1096 map
["{pattern_base}/repos/[^/]*/[^/]*/statuses/[a-f0-9]+$".to_re
] = "RepoStatus"
1100 # Match `url` property in object to a class name
1101 fun url_heuristic
(raw
: Map[String, nullable Object]): nullable String do
1102 if not raw
.has_key
("url") then return null
1104 var url
= raw
["url"].as(String)
1105 for re
, class_name
in url_patterns
do
1106 if url
.has
(re
) then return class_name
1111 redef fun class_name_heuristic
(raw
) do
1113 var class_name
= url_heuristic
(raw
)
1114 if class_name
!= null then return class_name
1116 # print raw.serialize_to_json(true, true) # debug
1118 # Use properties heuristics
1119 if raw
.has_key
("name") and raw
.has_key
("commit") then
1121 else if raw
.has_key
("total_count") and raw
.has_key
("items") then
1122 return "SearchResults"
1123 else if raw
.has_key
("total") and raw
.has_key
("weeks") then
1124 return "ContributorStats"
1125 else if raw
.has_key
("a") and raw
.has_key
("d") and raw
.has_key
("c") then
1126 return "ContributorWeek"
1131 redef fun deserialize_class
(name
) do
1132 if name
== "Issue" then
1133 var issue
= super.as(Issue)
1134 if path
.last
.has_key
("pull_request") then
1135 issue
.is_pull_request
= true
1138 else if name
== "Commit" then
1139 var commit
= super.as(Commit)
1140 var git_commit
= commit
.commit
1141 if git_commit
!= null then commit
.message
= git_commit
.message
1148 # Gets the Github token from `git` configuration
1150 # Return the value of `git config --get github.oauthtoken`
1151 # or `""` if no key exists.
1152 fun get_github_oauth
: String
1154 var p
= new ProcessReader("git", "config", "--get", "github.oauthtoken")
1155 var token
= p
.read_line