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.
23 intrude import json
::serialization_read
25 # Client to Github API
27 # To access the API you need an instance of a `GithubAPI` client.
30 # # Get Github authentification token.
31 # var token = get_github_oauth
32 # assert not token.is_empty
35 # var api = new GithubAPI(token)
38 # The API client allows you to get Github API entities.
41 # var repo = api.load_repo("nitlang/nit")
43 # assert repo.name == "nit"
45 # var user = api.load_user("Morriar")
47 # assert user.login == "Morriar"
51 # Github API OAuth token
53 # To access your private ressources, you must
54 # [authenticate](https://developer.github.com/guides/basics-of-authentication/).
56 # For client applications, Github recommands to use the
57 # [OAuth tokens](https://developer.github.com/v3/oauth/) authentification method.
61 # Be aware that there is [rate limits](https://developer.github.com/v3/rate_limit/)
62 # associated to the key.
65 # Github API base url.
67 # Default is `https://api.github.com` and should not be changed.
68 var api_url
= "https://api.github.com"
70 # User agent used for HTTP requests.
72 # Default is `nit_github_api`.
74 # See <https://developer.github.com/v3/#user-agent-required>
75 var user_agent
= "nit_github_api"
79 # Internal Curl instance used to perform API calls.
80 private var ghcurl
: GithubCurl is noinit
84 # * `0`: only errors (default)
86 var verbose_lvl
= 0 is public
writable
89 ghcurl
= new GithubCurl(auth
, user_agent
)
92 # Deserialize an object
93 fun deserialize
(string
: String): nullable Object do
94 var deserializer
= new GithubDeserializer(string
)
95 var res
= deserializer
.deserialize
96 # print deserializer.errors.join("\n") # DEBUG
100 # Execute a GET request on Github API.
102 # This method returns raw json data.
103 # See other `load_*` methods to use more expressive types.
105 # var api = new GithubAPI(get_github_oauth)
106 # var obj = api.get("/repos/nitlang/nit")
107 # assert obj isa JsonObject
108 # assert obj["name"] == "nit"
110 # Returns `null` in case of `error`.
112 # obj = api.get("/foo/bar/baz")
114 # assert api.was_error
115 # var err = api.last_error
116 # assert err isa GithubError
117 # assert err.name == "GithubAPIError"
118 # assert err.message == "Not Found"
119 fun get
(path
: String): nullable Jsonable do
120 path
= sanitize_uri
(path
)
121 var res
= ghcurl
.get_and_parse
("{api_url}{path}")
122 if res
isa Error then
131 # Display a message depending on `verbose_lvl`.
132 fun message
(lvl
: Int, message
: String) do
133 if lvl
<= verbose_lvl
then print message
136 # Escape `uri` in an acceptable format for Github.
137 private fun sanitize_uri
(uri
: String): String do
138 # TODO better URI escape.
139 return uri
.replace
(" ", "%20")
142 # Last error occured during Github API communications.
143 var last_error
: nullable Error = null is public
writable
145 # Does the last request provoqued an error?
146 var was_error
= false is protected writable
148 # Load the json object from Github.
149 # See `GithubEntity::load_from_github`.
150 protected fun load_from_github
(key
: String): nullable GithubEntity do
151 message
(1, "Get {key} (github)")
153 if was_error
then return null
154 return deserialize
(res
.as(JsonObject).to_json
).as(nullable GithubEntity)
157 # Get the Github logged user from `auth` token.
159 # Loads the `User` from the API or returns `null` if the user cannot be found.
162 # var api = new GithubAPI(get_github_oauth)
163 # var user = api.load_auth_user
164 # assert user.login == "Morriar"
166 fun load_auth_user
: nullable User do
167 var user
= load_from_github
("/user")
168 if was_error
then return null
169 return user
.as(nullable User)
172 # Get the Github user with `login`
174 # Loads the `User` from the API or returns `null` if the user cannot be found.
176 # var api = new GithubAPI(get_github_oauth)
177 # var user = api.load_user("Morriar")
178 # print user or else "null"
179 # assert user.login == "Morriar"
180 fun load_user
(login
: String): nullable User do
181 return load_from_github
("/users/{login}").as(nullable User)
184 # Get the Github repo with `full_name`.
186 # Loads the `Repo` from the API or returns `null` if the repo cannot be found.
188 # var api = new GithubAPI(get_github_oauth)
189 # var repo = api.load_repo("nitlang/nit")
190 # assert repo.name == "nit"
191 # assert repo.owner.login == "nitlang"
192 # assert repo.default_branch == "master"
193 fun load_repo
(full_name
: String): nullable Repo do
194 return load_from_github
("/repos/{full_name}").as(nullable Repo)
197 # List of branches associated with their names.
198 fun load_repo_branches
(repo
: Repo): Array[Branch] do
199 message
(1, "Get branches for {repo.full_name}")
200 var array
= get
("/repos/{repo.full_name}/branches")
201 var res
= new Array[Branch]
202 if not array
isa JsonArray then return res
203 return deserialize
(array
.to_json
).as(Array[Branch])
206 # List of issues associated with their ids.
207 fun load_repo_issues
(repo
: Repo): Array[Issue] do
208 message
(1, "Get issues for {repo.full_name}")
209 var res
= new Array[Issue]
210 var issue
= load_repo_last_issue
(repo
)
211 if issue
== null then return res
213 while issue
!= null and issue
.number
> 1 do
214 issue
= load_issue
(repo
, issue
.number
- 1)
215 if issue
== null then continue
221 # Search issues in this repo form an advanced query.
226 # var issues = repo.search_issues("is:open label:need_review")
229 # See <https://developer.github.com/v3/search/#search-issues>.
230 fun search_repo_issues
(repo
: Repo, query
: String): Array[Issue] do
231 query
= "/search/issues?q={query} repo:{repo.full_name}"
232 var res
= new Array[Issue]
233 var response
= get
(query
)
234 if was_error
then return res
235 var arr
= response
.as(JsonObject)["items"].as(JsonArray)
236 return deserialize
(arr
.to_json
).as(Array[Issue])
239 # Get the last published issue.
240 fun load_repo_last_issue
(repo
: Repo): nullable Issue do
241 var array
= get
("/repos/{repo.full_name}/issues")
242 if not array
isa JsonArray then return null
243 if array
.is_empty
then return null
244 var obj
= array
.first
245 if not obj
isa JsonObject then return null
246 return deserialize
(obj
.to_json
).as(nullable Issue)
249 # List of labels associated with their names.
250 fun load_repo_labels
(repo
: Repo): Array[Label] do
251 message
(1, "Get labels for {repo.full_name}")
252 var array
= get
("repos/{repo.full_name}/labels")
253 if not array
isa JsonArray then return new Array[Label]
254 return deserialize
(array
.to_json
).as(Array[Label])
257 # List of milestones associated with their ids.
258 fun load_repo_milestones
(repo
: Repo): Array[Milestone] do
259 message
(1, "Get milestones for {repo.full_name}")
260 var array
= get
("/repos/{repo.full_name}/milestones")
261 if not array
isa JsonArray then return new Array[Milestone]
262 return deserialize
(array
.to_json
).as(Array[Milestone])
265 # List of pull-requests associated with their ids.
267 # Implementation notes: because PR numbers are not consecutive,
268 # PR are loaded from pages.
269 # See: https://developer.github.com/v3/pulls/#list-pull-requests
270 fun load_repo_pulls
(repo
: Repo): Array[PullRequest] do
271 message
(1, "Get pulls for {repo.full_name}")
272 var key
= "/repos/{repo.full_name}"
273 var res
= new Array[PullRequest]
276 var array
= get
("{key}/pulls?page={page}").as(JsonArray)
277 if array
.is_empty
then break
279 if not obj
isa JsonObject then continue
280 var pr
= deserialize
(array
.to_json
).as(nullable PullRequest)
281 if pr
== null then continue
289 # List of contributor related statistics.
290 fun load_repo_contrib_stats
(repo
: Repo): Array[ContributorStats] do
291 message
(1, "Get contributor stats for {repo.full_name}")
292 var res
= new Array[ContributorStats]
293 var array
= get
("/repos/{repo.full_name}/stats/contributors")
294 if not array
isa JsonArray then return res
295 return deserialize
(array
.to_json
).as(Array[ContributorStats])
298 # Get the Github branch with `name`.
300 # Returns `null` if the branch cannot be found.
302 # var api = new GithubAPI(get_github_oauth)
303 # var repo = api.load_repo("nitlang/nit")
304 # assert repo != null
305 # var branch = api.load_branch(repo, "master")
306 # assert branch.name == "master"
307 # assert branch.commit isa Commit
308 fun load_branch
(repo
: Repo, name
: String): nullable Branch do
309 return load_from_github
("/repos/{repo.full_name}/branches/{name}").as(nullable Branch)
312 # List all commits in `self`.
314 # This can be long depending on the branch size.
315 # Commit are returned in an unspecified order.
316 fun load_branch_commits
(branch
: Branch): Array[Commit] do
317 var res
= new Array[Commit]
318 var done
= new HashSet[String]
319 var todos
= new Array[Commit]
320 todos
.add branch
.commit
322 if todos
.is_empty
then break
323 var commit
= todos
.pop
324 if done
.has
(commit
.sha
) then continue
327 var parents
= commit
.parents
328 if parents
== null then continue
329 for parent
in parents
do
336 # Get the Github commit with `sha`.
338 # Returns `null` if the commit cannot be found.
340 # var api = new GithubAPI(get_github_oauth)
341 # var repo = api.load_repo("nitlang/nit")
342 # assert repo != null
343 # var commit = api.load_commit(repo, "64ce1f")
344 # assert commit isa Commit
345 fun load_commit
(repo
: Repo, sha
: String): nullable Commit do
346 return load_from_github
("/repos/{repo.full_name}/commits/{sha}").as(nullable Commit)
349 # Get the Github issue #`number`.
351 # Returns `null` if the issue cannot be found.
353 # var api = new GithubAPI(get_github_oauth)
354 # var repo = api.load_repo("nitlang/nit")
355 # assert repo != null
356 # var issue = api.load_issue(repo, 1)
357 # assert issue.title == "Doc"
358 fun load_issue
(repo
: Repo, number
: Int): nullable Issue do
359 return load_from_github
("/repos/{repo.full_name}/issues/{number}").as(nullable Issue)
362 # List of event on this issue.
363 fun load_issue_comments
(repo
: Repo, issue
: Issue): Array[IssueComment] do
364 var res
= new Array[IssueComment]
365 var count
= issue
.comments
or else 0
368 var array
= get
("/repos/{repo.full_name}/issues/{issue.number}/comments?page={page}")
369 if not array
isa JsonArray then break
370 if array
.is_empty
then break
372 if not obj
isa JsonObject then continue
373 var id
= obj
["id"].as(Int)
374 var comment
= load_issue_comment
(repo
, id
)
375 if comment
== null then continue
378 if res
.length
>= count
then break
384 # List of events on this issue.
385 fun load_issue_events
(repo
: Repo, issue
: Issue): Array[IssueEvent] do
386 var res
= new Array[IssueEvent]
387 var key
= "/repos/{repo.full_name}/issues/{issue.number}"
390 var array
= get
("{key}/events?page={page}")
391 if not array
isa JsonArray or array
.is_empty
then break
393 if not obj
isa JsonObject then continue
394 var event
= deserialize
(obj
.to_json
).as(nullable IssueEvent)
395 if event
== null then continue
403 # Get the Github pull request #`number`.
405 # Returns `null` if the pull request cannot be found.
407 # var api = new GithubAPI(get_github_oauth)
408 # var repo = api.load_repo("nitlang/nit")
409 # assert repo != null
410 # var pull = api.load_pull(repo, 1)
411 # assert pull.title == "Doc"
412 # assert pull.user.login == "Morriar"
413 fun load_pull
(repo
: Repo, number
: Int): nullable PullRequest do
414 return load_from_github
("/repos/{repo.full_name}/pulls/{number}").as(nullable PullRequest)
417 # Get the Github label with `name`.
419 # Returns `null` if the label cannot be found.
421 # var api = new GithubAPI(get_github_oauth)
422 # var repo = api.load_repo("nitlang/nit")
423 # assert repo != null
424 # var labl = api.load_label(repo, "ok_will_merge")
425 # assert labl != null
426 fun load_label
(repo
: Repo, name
: String): nullable Label do
427 return load_from_github
("/repos/{repo.full_name}/labels/{name}").as(nullable Label)
430 # Get the Github milestone with `id`.
432 # Returns `null` if the milestone cannot be found.
434 # var api = new GithubAPI(get_github_oauth)
435 # var repo = api.load_repo("nitlang/nit")
436 # assert repo != null
437 # var stone = api.load_milestone(repo, 4)
438 # assert stone.title == "v1.0prealpha"
439 fun load_milestone
(repo
: Repo, id
: Int): nullable Milestone do
440 return load_from_github
("/repos/{repo.full_name}/milestones/{id}").as(nullable Milestone)
443 # Get the Github issue event with `id`.
445 # Returns `null` if the event cannot be found.
447 # var api = new GithubAPI(get_github_oauth)
448 # var repo = api.load_repo("nitlang/nit")
449 # assert repo isa Repo
450 # var event = api.load_issue_event(repo, 199674194)
451 # assert event isa IssueEvent
452 # assert event.actor.login == "privat"
453 # assert event.event == "labeled"
454 # assert event.labl isa Label
455 # assert event.labl.name == "need_review"
456 fun load_issue_event
(repo
: Repo, id
: Int): nullable IssueEvent do
457 return load_from_github
("/repos/{repo.full_name}/issues/events/{id}").as(nullable IssueEvent)
460 # Get the Github commit comment with `id`.
462 # Returns `null` if the comment cannot be found.
464 # var api = new GithubAPI(get_github_oauth)
465 # var repo = api.load_repo("nitlang/nit")
466 # assert repo != null
467 # var comment = api.load_commit_comment(repo, 8982707)
468 # assert comment.user.login == "Morriar"
469 # assert comment.body == "For testing purposes...\n"
470 # assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
471 fun load_commit_comment
(repo
: Repo, id
: Int): nullable CommitComment do
472 return load_from_github
("/repos/{repo.full_name}/comments/{id}").as(nullable CommitComment)
475 # Get the Github issue comment with `id`.
477 # Returns `null` if the comment cannot be found.
479 # var api = new GithubAPI(get_github_oauth)
480 # var repo = api.load_repo("nitlang/nit")
481 # assert repo != null
482 # var comment = api.load_issue_comment(repo, 6020149)
483 # assert comment.user.login == "privat"
484 # assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
485 # assert comment.issue_number == 10
486 fun load_issue_comment
(repo
: Repo, id
: Int): nullable IssueComment do
487 return load_from_github
("/repos/{repo.full_name}/issues/comments/{id}").as(nullable IssueComment)
490 # Get the Github diff comment with `id`.
492 # Returns `null` if the comment cannot be found.
494 # var api = new GithubAPI(get_github_oauth)
495 # var repo = api.load_repo("nitlang/nit")
496 # assert repo != null
497 # var comment = api.load_review_comment(repo, 21010363)
498 # assert comment.path == "src/modelize/modelize_property.nit"
499 # assert comment.original_position == 26
500 # assert comment.pull_number == 945
501 fun load_review_comment
(repo
: Repo, id
: Int): nullable ReviewComment do
502 return load_from_github
("/repos/{repo.full_name}/pulls/comments/{id}").as(nullable ReviewComment)
506 # Something returned by the Github API.
508 # Mainly a Nit wrapper around a JSON objet.
509 abstract class GithubEntity
514 var html_url
: nullable String is writable
519 # Provides access to [Github user data](https://developer.github.com/v3/users/).
520 # Should be accessed from `GithubAPI::load_user`.
526 var login
: String is writable
528 # Avatar image url for this user.
529 var avatar_url
: nullable String is writable
531 # User public name if any.
532 var name
: nullable String is writable
534 # User public email if any.
535 var email
: nullable String is writable
537 # User public blog if any.
538 var blog
: nullable String is writable
541 # A Github repository.
543 # Provides access to [Github repo data](https://developer.github.com/v3/repos/).
544 # Should be accessed from `GithubAPI::load_repo`.
549 # Repo full name on Github.
550 var full_name
: String is writable
552 # Repo short name on Github.
553 var name
: String is writable
555 # Get the repo owner.
556 var owner
: User is writable
558 # Repo default branch name.
559 var default_branch
: String is writable
564 # Should be accessed from `GithubAPI::load_branch`.
566 # See <https://developer.github.com/v3/repos/#list-branches>.
572 var name
: String is writable
574 # Get the last commit of `self`.
575 var commit
: Commit is writable
580 # Should be accessed from `GithubAPI::load_commit`.
582 # See <https://developer.github.com/v3/repos/commits/>.
588 var sha
: String is writable
590 # Parent commits of `self`.
591 var parents
: nullable Array[Commit] = null is writable
593 # Author of the commit.
594 var author
: nullable User is writable
596 # Committer of the commit.
597 var committer
: nullable User is writable
599 # Authoring date as String.
600 var author_date
: nullable String is writable
602 # Authoring date as ISODate.
603 fun iso_author_date
: nullable ISODate do
604 var author_date
= self.author_date
605 if author_date
== null then return null
606 return new ISODate.from_string
(author_date
)
609 # Commit date as String.
610 var commit_date
: nullable String is writable
612 # Commit date as ISODate.
613 fun iso_commit_date
: nullable ISODate do
614 var commit_date
= self.commit_date
615 if commit_date
== null then return null
616 return new ISODate.from_string
(commit_date
)
619 # List files staged in this commit.
620 var files
: nullable Array[GithubFile] = null is optional
, writable
623 var message
: nullable String is writable
628 # Should be accessed from `GithubAPI::load_issue`.
630 # See <https://developer.github.com/v3/issues/>.
636 var number
: Int is writable
639 var id
: nullable Int is writable
642 var title
: String is writable
644 # User that created this issue.
645 var user
: nullable User is writable
647 # List of labels on this issue associated to their names.
648 var labels
: nullable Array[Label] is writable
650 # State of the issue on Github.
651 var state
: String is writable
653 # Is the issue locked?
654 var locked
: nullable Bool is writable
656 # Assigned `User` (if any).
657 var assignee
: nullable User is writable
659 # `Milestone` (if any).
660 var milestone
: nullable Milestone is writable
662 # Number of comments on this issue.
663 var comments
: nullable Int is writable
665 # Creation time as String.
666 var created_at
: String is writable
668 # Creation time as ISODate.
669 fun iso_created_at
: ISODate do
670 return new ISODate.from_string
(created_at
)
673 # Last update time as String (if any).
674 var updated_at
: nullable String is writable
676 # Last update date as ISODate.
677 fun iso_updated_at
: nullable ISODate do
678 var updated_at
= self.updated_at
679 if updated_at
== null then return null
680 return new ISODate.from_string
(updated_at
)
683 # Close time as String (if any).
684 var closed_at
: nullable String is writable
686 # Close time as ISODate.
687 fun iso_closed_at
: nullable ISODate do
688 var closed_at
= self.closed_at
689 if closed_at
== null then return null
690 return new ISODate.from_string
(closed_at
)
693 # Full description of the issue.
694 var body
: nullable String is writable
696 # User that closed this issue (if any).
697 var closed_by
: nullable User is writable
699 # Is this issue linked to a pull request?
700 var is_pull_request
: Bool = false is writable, noserialize
703 # A Github pull request.
705 # Should be accessed from `GithubAPI::load_pull`.
707 # PullRequest are basically Issues with more data.
708 # See <https://developer.github.com/v3/pulls/>.
713 # Merge time as String (if any).
714 var merged_at
: nullable String is writable
716 # Merge time as ISODate.
717 fun iso_merged_at
: nullable ISODate do
718 var merged_at
= self.merged_at
719 if merged_at
== null then return null
720 return new ISODate.from_string
(merged_at
)
724 var merge_commit_sha
: nullable String is writable
726 # Count of comments made on the pull request diff.
727 var review_comments
: Int is writable
729 # Pull request head (can be a commit SHA or a branch name).
730 var head
: PullRef is writable
732 # Pull request base (can be a commit SHA or a branch name).
733 var base
: PullRef is writable
735 # Is this pull request merged?
736 var merged
: Bool is writable
738 # Is this pull request mergeable?
739 var mergeable
: nullable Bool is writable
741 # Mergeable state of this pull request.
743 # See <https://developer.github.com/v3/pulls/#list-pull-requests>.
744 var mergeable_state
: String is writable
746 # User that merged this pull request (if any).
747 var merged_by
: nullable User is writable
749 # Count of commits in this pull request.
750 var commits
: Int is writable
753 var additions
: Int is writable
755 # Deleted line count.
756 var deletions
: Int is writable
758 # Changed files count.
759 var changed_files
: Int is writable
762 # A pull request reference (used for head and base).
766 # Label pointed by `self`.
767 var labl
: String is writable, serialize_as
("label")
769 # Reference pointed by `self`.
770 var ref
: String is writable
772 # Commit SHA pointed by `self`.
773 var sha
: String is writable
775 # User pointed by `self`.
776 var user
: User is writable
778 # Repo pointed by `self` (if any).
780 # A `null` value means the `repo` was deleted.
781 var repo
: nullable Repo is writable
786 # Should be accessed from `GithubAPI::load_label`.
788 # See <https://developer.github.com/v3/issues/labels/>.
794 var name
: String is writable
797 var color
: String is writable
800 # A Github milestone.
802 # Should be accessed from `GithubAPI::load_milestone`.
804 # See <https://developer.github.com/v3/issues/milestones/>.
809 # The milestone id on Github.
810 var number
: Int is writable
813 var title
: String is writable
815 # Milestone long description.
816 var description
: String is writable
818 # Count of opened issues linked to this milestone.
819 var open_issues
: Int is writable
821 # Count of closed issues linked to this milestone.
822 var closed_issues
: Int is writable
825 var state
: String is writable
827 # Creation time as String.
828 var created_at
: String is writable
830 # Creation time as ISODate.
831 fun iso_created_at
: nullable ISODate do return new ISODate.from_string
(created_at
)
833 # User that created this milestone.
834 var creator
: User is writable
836 # Due time as String (if any).
837 var due_on
: nullable String is writable
839 # Due time in ISODate format (if any).
840 fun iso_due_on
: nullable ISODate do
841 var due_on
= self.due_on
842 if due_on
== null then return null
843 return new ISODate.from_string
(due_on
)
846 # Last update time as String (if any).
847 var updated_at
: nullable String is writable
849 # Last update date as ISODate.
850 fun iso_updated_at
: nullable ISODate do
851 var updated_at
= self.updated_at
852 if updated_at
== null then return null
853 return new ISODate.from_string
(updated_at
)
856 # Close time as String (if any).
857 var closed_at
: nullable String is writable
859 # Close time as ISODate.
860 fun iso_closed_at
: nullable ISODate do
861 var closed_at
= self.closed_at
862 if closed_at
== null then return null
863 return new ISODate.from_string
(closed_at
)
869 # There is two kinds of comments:
871 # * `CommitComment` are made on a commit page.
872 # * `IssueComment` are made on an issue or pull request page.
873 # * `ReviewComment` are made on the diff associated to a pull request.
874 abstract class Comment
878 # Identifier of this comment.
879 var id
: Int is writable
881 # User that made this comment.
882 var user
: User is writable
884 # Creation time as String.
885 var created_at
: String is writable
887 # Creation time as ISODate.
888 fun iso_created_at
: nullable ISODate do
889 return new ISODate.from_string
(created_at
)
892 # Last update time as String (if any).
893 var updated_at
: nullable String is writable
895 # Last update date as ISODate.
896 fun iso_updated_at
: nullable ISODate do
897 var updated_at
= self.updated_at
898 if updated_at
== null then return null
899 return new ISODate.from_string
(updated_at
)
903 var body
: String is writable
905 # Does the comment contain an acknowledgement (+1)
907 return body
.has
("\\+1\\b".to_re
) or body
.has
(":+1:") or body
.has
(":shipit:")
911 # A comment made on a commit.
917 var commit_id
: String is writable
919 # Position of the comment on the line.
920 var position
: nullable Int is writable
922 # Line of the comment.
923 var line
: nullable Int is writable
925 # Path of the commented file.
926 var path
: nullable String is writable
929 # Comments made on Github issue and pull request pages.
931 # Should be accessed from `GithubAPI::load_issue_comment`.
933 # See <https://developer.github.com/v3/issues/comments/>.
938 # Issue that contains `self`.
939 fun issue_number
: Int do return issue_url
.split
("/").last
.to_i
941 # Link to the issue document on API.
942 var issue_url
: String is writable
945 # Comments made on Github pull request diffs.
947 # Should be accessed from `GithubAPI::load_diff_comment`.
949 # See <https://developer.github.com/v3/pulls/comments/>.
954 # Pull request that contains `self`.
955 fun pull_number
: Int do return pull_request_url
.split
("/").last
.to_i
957 # Link to the pull request on API.
958 var pull_request_url
: String is writable
961 var diff_hunk
: String is writable
963 # Path of commented file.
964 var path
: String is writable
966 # Position of the comment on the file.
967 var position
: nullable Int is writable
969 # Original position in the diff.
970 var original_position
: Int is writable
972 # Commit referenced by this comment.
973 var commit_id
: String is writable
975 # Original commit id.
976 var original_commit_id
: String is writable
979 # An event that occurs on a Github `Issue`.
981 # Should be accessed from `GithubAPI::load_issue_event`.
983 # See <https://developer.github.com/v3/issues/events/>.
988 # Event id on Github.
989 var id
: Int is writable
991 # User that initiated the event.
992 var actor
: User is writable
994 # Creation time as String.
995 var created_at
: String is writable
997 # Creation time as ISODate.
998 fun iso_created_at
: nullable ISODate do
999 return new ISODate.from_string
(created_at
)
1003 var event
: String is writable
1005 # Commit linked to this event (if any).
1006 var commit_id
: nullable String is writable
1008 # Label linked to this event (if any).
1009 var labl
: nullable Label is writable, serialize_as
("label")
1011 # User linked to this event (if any).
1012 var assignee
: nullable User is writable
1014 # Milestone linked to this event (if any).
1015 var milestone
: nullable Milestone is writable
1017 # Rename linked to this event (if any).
1018 var rename
: nullable RenameAction is writable
1021 # A rename action maintains the name before and after a renaming action.
1025 # Name before renaming.
1026 var from
: String is writable
1028 # Name after renaming.
1029 var to
: String is writable
1033 # Should be accessed from `Repo::contrib_stats`.
1035 # See <https://developer.github.com/v3/repos/statistics/>.
1036 class ContributorStats
1040 redef type OTHER: ContributorStats
1042 # Github API client.
1043 var api
: GithubAPI is writable
1045 # User these statistics are about.
1046 var author
: User is writable
1048 # Total number of commit.
1049 var total
: Int is writable
1051 # Are of weeks of activity with detailed statistics.
1052 var weeks
: JsonArray is writable
1054 # ContributorStats can be compared on the total amount of commits.
1055 redef fun <(o
) do return total
< o
.total
1058 # A Github file representation.
1060 # Mostly a wrapper around a json object.
1065 var filename
: String is writable
1068 # Make ISO Datew serilizable
1074 # JsonDeserializer specific for Github objects.
1075 class GithubDeserializer
1076 super JsonDeserializer
1078 redef fun class_name_heuristic
(json_object
) do
1079 if json_object
.has_key
("login") or json_object
.has_key
("email") then
1081 else if json_object
.has_key
("full_name") then
1083 else if json_object
.has_key
("name") and json_object
.has_key
("commit") then
1085 else if json_object
.has_key
("sha") and json_object
.has_key
("ref") then
1087 else if json_object
.has_key
("sha") or (json_object
.has_key
("id") and json_object
.has_key
("tree_id")) then
1089 else if json_object
.has_key
("number") and json_object
.has_key
("patch_url") then
1090 return "PullRequest"
1091 else if json_object
.has_key
("open_issues") and json_object
.has_key
("closed_issues") then
1093 else if json_object
.has_key
("number") and json_object
.has_key
("title") then
1095 else if json_object
.has_key
("color") then
1097 else if json_object
.has_key
("event") then
1099 else if json_object
.has_key
("original_commit_id") then
1100 return "ReviewComment"
1101 else if json_object
.has_key
("commit_id") then
1102 return "CommitComment"
1103 else if json_object
.has_key
("issue_url") then
1104 return "IssueComment"
1109 redef fun deserialize_class
(name
) do
1110 if name
== "Issue" then
1111 var issue
= super.as(Issue)
1112 if path
.last
.has_key
("pull_request") then
1113 issue
.is_pull_request
= true