4a38fe524f1c0d019e845d482284b4840611ccf4
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
30 # Client to Github API
32 # To access the API you need an instance of a `GithubAPI` client.
35 # # Get Github authentification token.
36 # var token = get_github_oauth
37 # assert not token.is_empty
40 # var api = new GithubAPI(token)
43 # The API client allows you to get Github API entities.
46 # var repo = api.load_repo("nitlang/nit")
48 # assert repo.name == "nit"
50 # var user = api.load_user("Morriar")
52 # assert user.login == "Morriar"
56 # Github API OAuth token
58 # To access your private ressources, you must
59 # [authenticate](https://developer.github.com/guides/basics-of-authentication/).
61 # For client applications, Github recommands to use the
62 # [OAuth tokens](https://developer.github.com/v3/oauth/) authentification method.
66 # Be aware that there is [rate limits](https://developer.github.com/v3/rate_limit/)
67 # associated to the key.
68 var auth
: nullable String = null is optional
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
: String = "nit_github_api" is optional
77 # Headers to use on all requests
78 fun new_headers
: HeaderMap do
79 var map
= new HeaderMap
82 map
["Authorization"] = "token {auth}"
84 map
["User-Agent"] = user_agent
85 # FIXME remove when projects and team are no more in beta
86 map
["Accept"] = "application/vnd.github.inertia-preview+json"
87 map
["Accept"] = "application/vnd.github.hellcat-preview+json"
91 # Github API base url.
93 # Default is `https://api.github.com` and should not be changed.
94 var api_url
= "https://api.github.com"
98 # * `0`: only errors (default)
100 var verbose_lvl
= 0 is public
writable
102 # Send a HTTPRequest to the Github API
103 fun send
(method
, path
: String, headers
: nullable HeaderMap, body
: nullable String): nullable String do
105 path
= sanitize_uri
(path
)
106 var uri
= "{api_url}{path}"
107 var request
= new CurlHTTPRequest(uri
)
108 request
.method
= method
109 request
.user_agent
= user_agent
110 request
.headers
= headers
or else self.new_headers
112 return check_response
(uri
, request
.execute
)
115 private fun check_response
(uri
: String, response
: CurlResponse): nullable String do
116 if response
isa CurlResponseSuccess then
118 return response
.body_str
119 else if response
isa CurlResponseFailed then
120 last_error
= new GithubAPIError(
130 # Deserialize an object
131 fun deserialize
(string
: nullable Serializable): nullable Object do
132 if string
== null then return null
133 var deserializer
= new GithubDeserializer(string
.to_s
)
134 var res
= deserializer
.deserialize
135 if deserializer
.errors
.not_empty
then
137 last_error
= new GithubDeserializerErrors("Deserialization failed", deserializer
.errors
)
139 else if res
isa GithubError then
148 # Execute a GET request on Github API.
150 # This method returns raw json data.
151 # See other `load_*` methods to use more expressive types.
154 # var api = new GithubAPI(get_github_oauth)
155 # var obj = api.get("/repos/nitlang/nit")
156 # assert obj isa JsonObject
157 # assert obj["name"] == "nit"
160 # Returns `null` in case of `error`.
163 # obj = api.get("/foo/bar/baz")
165 # assert api.was_error
166 # var err = api.last_error
167 # assert err isa GithubError
168 # assert err.name == "GithubAPIError"
169 # assert err.message == "Not Found"
171 fun get
(path
: String): nullable String do
172 return send
("GET", path
)
175 # Display a message depending on `verbose_lvl`.
176 fun message
(lvl
: Int, message
: String) do
177 if lvl
<= verbose_lvl
then print message
180 # Escape `uri` in an acceptable format for Github.
181 private fun sanitize_uri
(uri
: String): String do
182 # TODO better URI escape.
183 return uri
.replace
(" ", "%20")
186 # Last error occured during Github API communications.
187 var last_error
: nullable Error = null is public
writable
189 # Does the last request provoqued an error?
190 var was_error
= false is protected writable
192 # Load the json object from Github.
193 # See `GithubEntity::load_from_github`.
194 protected fun load_from_github
(key
: String): nullable GithubEntity do
195 message
(1, "Get {key} (github)")
197 if res
== null then return null
198 return deserialize
(res
).as(nullable GithubEntity)
201 # Get the Github logged user from `auth` token.
203 # Loads the `User` from the API or returns `null` if the user cannot be found.
206 # var api = new GithubAPI(get_github_oauth)
207 # var user = api.load_auth_user
208 # assert user.login == "Morriar"
210 fun load_auth_user
: nullable User do
211 var user
= load_from_github
("/user")
212 if was_error
then return null
213 return user
.as(nullable User)
216 # Get the Github user with `login`
218 # Loads the `User` from the API or returns `null` if the user cannot be found.
221 # var api = new GithubAPI(get_github_oauth)
222 # var user = api.load_user("Morriar")
223 # print user or else "null"
224 # assert user.login == "Morriar"
226 fun load_user
(login
: String): nullable User do
227 return load_from_github
("/users/{login}").as(nullable User)
230 # Get the Github repo with `full_name`.
232 # Loads the `Repo` from the API or returns `null` if the repo cannot be found.
235 # var api = new GithubAPI(get_github_oauth)
236 # var repo = api.load_repo("nitlang/nit")
237 # assert repo.name == "nit"
238 # assert repo.owner.login == "nitlang"
239 # assert repo.default_branch == "master"
241 fun load_repo
(full_name
: String): nullable Repo do
242 return load_from_github
("/repos/{full_name}").as(nullable Repo)
245 # List of branches associated with their names.
246 fun load_repo_branches
(repo
: Repo): Array[Branch] do
247 message
(1, "Get branches for {repo.full_name}")
248 var array
= get
("/repos/{repo.full_name}/branches")
249 var res
= new Array[Branch]
250 if array
== null then return res
251 var deser
= deserialize
(array
)
252 if not deser
isa Array[Object] then return res
# empty array
253 for branch
in deser
do
254 if not branch
isa Branch then continue
260 # List of issues associated with their ids.
261 fun load_repo_issues
(repo
: Repo): Array[Issue] do
262 message
(1, "Get issues for {repo.full_name}")
263 var res
= new Array[Issue]
264 var issue
= load_repo_last_issue
(repo
)
265 if issue
== null then return res
267 while issue
!= null and issue
.number
> 1 do
268 issue
= load_issue
(repo
, issue
.number
- 1)
269 if issue
== null then continue
275 # Search issues in this repo form an advanced query.
280 # var issues = repo.search_issues("is:open label:need_review")
283 # See <https://developer.github.com/v3/search/#search-issues>.
284 fun search_repo_issues
(repo
: Repo, query
: String): Array[Issue] do
285 query
= "/search/issues?q={query} repo:{repo.full_name}"
286 var res
= new Array[Issue]
287 var response
= get
(query
)
288 if was_error
then return res
289 var arr
= response
.as(JsonObject)["items"].as(JsonArray)
290 return deserialize
(arr
.to_json
).as(Array[Issue])
293 # Get the last published issue.
294 fun load_repo_last_issue
(repo
: Repo): nullable Issue do
295 var array
= get
("/repos/{repo.full_name}/issues")
296 if not array
isa JsonArray then return null
297 if array
.is_empty
then return null
298 var obj
= array
.first
299 if not obj
isa JsonObject then return null
300 return deserialize
(obj
.to_json
).as(nullable Issue)
303 # List of labels associated with their names.
304 fun load_repo_labels
(repo
: Repo): Array[Label] do
305 message
(1, "Get labels for {repo.full_name}")
306 var array
= get
("repos/{repo.full_name}/labels")
307 if not array
isa JsonArray then return new Array[Label]
308 return deserialize
(array
.to_json
).as(Array[Label])
311 # List of milestones associated with their ids.
312 fun load_repo_milestones
(repo
: Repo): Array[Milestone] do
313 message
(1, "Get milestones for {repo.full_name}")
314 var array
= get
("/repos/{repo.full_name}/milestones")
315 if not array
isa JsonArray then return new Array[Milestone]
316 return deserialize
(array
.to_json
).as(Array[Milestone])
319 # List of pull-requests associated with their ids.
321 # Implementation notes: because PR numbers are not consecutive,
322 # PR are loaded from pages.
323 # See: https://developer.github.com/v3/pulls/#list-pull-requests
324 fun load_repo_pulls
(repo
: Repo): Array[PullRequest] do
325 message
(1, "Get pulls for {repo.full_name}")
326 var key
= "/repos/{repo.full_name}"
327 var res
= new Array[PullRequest]
330 var array
= get
("{key}/pulls?page={page}").as(JsonArray)
331 if array
.is_empty
then break
333 if not obj
isa JsonObject then continue
334 var pr
= deserialize
(array
.to_json
).as(nullable PullRequest)
335 if pr
== null then continue
343 # List of contributor related statistics.
344 fun load_repo_contrib_stats
(repo
: Repo): Array[ContributorStats] do
345 message
(1, "Get contributor stats for {repo.full_name}")
346 var res
= new Array[ContributorStats]
347 var array
= get
("/repos/{repo.full_name}/stats/contributors")
348 if not array
isa JsonArray then return res
349 return deserialize
(array
.to_json
).as(Array[ContributorStats])
352 # Get the Github branch with `name`.
354 # Returns `null` if the branch cannot be found.
357 # var api = new GithubAPI(get_github_oauth)
358 # var repo = api.load_repo("nitlang/nit")
359 # assert repo != null
360 # var branch = api.load_branch(repo, "master")
361 # assert branch.name == "master"
362 # assert branch.commit isa Commit
364 fun load_branch
(repo
: Repo, name
: String): nullable Branch do
365 return load_from_github
("/repos/{repo.full_name}/branches/{name}").as(nullable Branch)
368 # List all commits in `self`.
370 # This can be long depending on the branch size.
371 # Commit are returned in an unspecified order.
372 fun load_branch_commits
(branch
: Branch): Array[Commit] do
373 var res
= new Array[Commit]
374 var done
= new HashSet[String]
375 var todos
= new Array[Commit]
376 todos
.add branch
.commit
378 if todos
.is_empty
then break
379 var commit
= todos
.pop
380 if done
.has
(commit
.sha
) then continue
383 var parents
= commit
.parents
384 if parents
== null then continue
385 for parent
in parents
do
392 # Get the Github commit with `sha`.
394 # Returns `null` if the commit cannot be found.
397 # var api = new GithubAPI(get_github_oauth)
398 # var repo = api.load_repo("nitlang/nit")
399 # assert repo != null
400 # var commit = api.load_commit(repo, "64ce1f")
401 # assert commit isa Commit
403 fun load_commit
(repo
: Repo, sha
: String): nullable Commit do
404 return load_from_github
("/repos/{repo.full_name}/commits/{sha}").as(nullable Commit)
407 # Get the Github issue #`number`.
409 # Returns `null` if the issue cannot be found.
412 # var api = new GithubAPI(get_github_oauth)
413 # var repo = api.load_repo("nitlang/nit")
414 # assert repo != null
415 # var issue = api.load_issue(repo, 1)
416 # assert issue.title == "Doc"
418 fun load_issue
(repo
: Repo, number
: Int): nullable Issue do
419 return load_from_github
("/repos/{repo.full_name}/issues/{number}").as(nullable Issue)
422 # List of event on this issue.
423 fun load_issue_comments
(repo
: Repo, issue
: Issue): Array[IssueComment] do
424 var res
= new Array[IssueComment]
425 var count
= issue
.comments
or else 0
428 var array
= get
("/repos/{repo.full_name}/issues/{issue.number}/comments?page={page}")
429 if not array
isa JsonArray then break
430 if array
.is_empty
then break
432 if not obj
isa JsonObject then continue
433 var id
= obj
["id"].as(Int)
434 var comment
= load_issue_comment
(repo
, id
)
435 if comment
== null then continue
438 if res
.length
>= count
then break
444 # List of events on this issue.
445 fun load_issue_events
(repo
: Repo, issue
: Issue): Array[IssueEvent] do
446 var res
= new Array[IssueEvent]
447 var key
= "/repos/{repo.full_name}/issues/{issue.number}"
450 var array
= get
("{key}/events?page={page}")
451 if not array
isa JsonArray or array
.is_empty
then break
453 if not obj
isa JsonObject then continue
454 var event
= deserialize
(obj
.to_json
).as(nullable IssueEvent)
455 if event
== null then continue
463 # Get the Github pull request #`number`.
465 # Returns `null` if the pull request cannot be found.
468 # var api = new GithubAPI(get_github_oauth)
469 # var repo = api.load_repo("nitlang/nit")
470 # assert repo != null
471 # var pull = api.load_pull(repo, 1)
472 # assert pull.title == "Doc"
473 # assert pull.user.login == "Morriar"
475 fun load_pull
(repo
: Repo, number
: Int): nullable PullRequest do
476 return load_from_github
("/repos/{repo.full_name}/pulls/{number}").as(nullable PullRequest)
479 # Get the Github label with `name`.
481 # Returns `null` if the label cannot be found.
484 # var api = new GithubAPI(get_github_oauth)
485 # var repo = api.load_repo("nitlang/nit")
486 # assert repo != null
487 # var labl = api.load_label(repo, "ok_will_merge")
488 # assert labl != null
490 fun load_label
(repo
: Repo, name
: String): nullable Label do
491 return load_from_github
("/repos/{repo.full_name}/labels/{name}").as(nullable Label)
494 # Get the Github milestone with `id`.
496 # Returns `null` if the milestone cannot be found.
499 # var api = new GithubAPI(get_github_oauth)
500 # var repo = api.load_repo("nitlang/nit")
501 # assert repo != null
502 # var stone = api.load_milestone(repo, 4)
503 # assert stone.title == "v1.0prealpha"
505 fun load_milestone
(repo
: Repo, id
: Int): nullable Milestone do
506 return load_from_github
("/repos/{repo.full_name}/milestones/{id}").as(nullable Milestone)
509 # Get the Github issue event with `id`.
511 # Returns `null` if the event cannot be found.
514 # var api = new GithubAPI(get_github_oauth)
515 # var repo = api.load_repo("nitlang/nit")
516 # assert repo isa Repo
517 # var event = api.load_issue_event(repo, 199674194)
518 # assert event isa IssueEvent
519 # assert event.actor.login == "privat"
520 # assert event.event == "labeled"
521 # assert event.labl isa Label
522 # assert event.labl.name == "need_review"
524 fun load_issue_event
(repo
: Repo, id
: Int): nullable IssueEvent do
525 return load_from_github
("/repos/{repo.full_name}/issues/events/{id}").as(nullable IssueEvent)
528 # Get the Github commit comment with `id`.
530 # Returns `null` if the comment cannot be found.
533 # var api = new GithubAPI(get_github_oauth)
534 # var repo = api.load_repo("nitlang/nit")
535 # assert repo != null
536 # var comment = api.load_commit_comment(repo, 8982707)
537 # assert comment.user.login == "Morriar"
538 # assert comment.body == "For testing purposes...\n"
539 # assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
541 fun load_commit_comment
(repo
: Repo, id
: Int): nullable CommitComment do
542 return load_from_github
("/repos/{repo.full_name}/comments/{id}").as(nullable CommitComment)
545 # Get the Github issue comment with `id`.
547 # Returns `null` if the comment cannot be found.
550 # var api = new GithubAPI(get_github_oauth)
551 # var repo = api.load_repo("nitlang/nit")
552 # assert repo != null
553 # var comment = api.load_issue_comment(repo, 6020149)
554 # assert comment.user.login == "privat"
555 # assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
556 # assert comment.issue_number == 10
558 fun load_issue_comment
(repo
: Repo, id
: Int): nullable IssueComment do
559 return load_from_github
("/repos/{repo.full_name}/issues/comments/{id}").as(nullable IssueComment)
562 # Get the Github diff comment with `id`.
564 # Returns `null` if the comment cannot be found.
567 # var api = new GithubAPI(get_github_oauth)
568 # var repo = api.load_repo("nitlang/nit")
569 # assert repo != null
570 # var comment = api.load_review_comment(repo, 21010363)
571 # assert comment.path == "src/modelize/modelize_property.nit"
572 # assert comment.original_position == 26
573 # assert comment.pull_number == 945
575 fun load_review_comment
(repo
: Repo, id
: Int): nullable ReviewComment do
576 return load_from_github
("/repos/{repo.full_name}/pulls/comments/{id}").as(nullable ReviewComment)
580 # An Error returned by GithubAPI
585 # An Error returned by https://api.github.com
587 # Anything that can occurs when sending request to the API:
588 # * Can't connect to API
589 # * Ressource not found
595 # Status code obtained
598 # URI that returned the error
599 var requested_uri
: String
602 # An Error returned while deserializing GithubEntity objects
603 class GithubDeserializerErrors
606 # Errors returned by the deserizalization process
607 var deserizalization_errors
: Array[Error]
610 # Something returned by the Github API.
612 # Mainly a Nit wrapper around a JSON objet.
613 abstract class GithubEntity
617 var html_url
: nullable String is writable
622 # Provides access to [Github user data](https://developer.github.com/v3/users/).
623 # Should be accessed from `GithubAPI::load_user`.
629 var login
: String is writable
631 # Avatar image url for this user.
632 var avatar_url
: nullable String is writable
634 # User public name if any.
635 var name
: nullable String is writable
637 # User public email if any.
638 var email
: nullable String is writable
640 # User public blog if any.
641 var blog
: nullable String is writable
644 # A Github repository.
646 # Provides access to [Github repo data](https://developer.github.com/v3/repos/).
647 # Should be accessed from `GithubAPI::load_repo`.
652 # Repo full name on Github.
653 var full_name
: String is writable
655 # Repo short name on Github.
656 var name
: String is writable
658 # Get the repo owner.
659 var owner
: User is writable
661 # Repo default branch name.
662 var default_branch
: String is writable
667 # Should be accessed from `GithubAPI::load_branch`.
669 # See <https://developer.github.com/v3/repos/#list-branches>.
675 var name
: String is writable
677 # Get the last commit of `self`.
678 var commit
: Commit is writable
683 # Should be accessed from `GithubAPI::load_commit`.
685 # See <https://developer.github.com/v3/repos/commits/>.
691 var sha
: String is writable
693 # Parent commits of `self`.
694 var parents
: nullable Array[Commit] = null is writable
696 # Author of the commit.
697 var author
: nullable GitUser is writable
699 # Committer of the commit.
700 var committer
: nullable GitUser is writable
702 # Authoring date as String.
703 var author_date
: nullable String is writable
705 # Authoring date as ISODate.
706 fun iso_author_date
: nullable ISODate do
707 var author_date
= self.author_date
708 if author_date
== null then return null
709 return new ISODate.from_string
(author_date
)
712 # Commit date as String.
713 var commit_date
: nullable String is writable
715 # Commit date as ISODate.
716 fun iso_commit_date
: nullable ISODate do
717 var commit_date
= self.commit_date
718 if commit_date
== null then return null
719 return new ISODate.from_string
(commit_date
)
722 # List files staged in this commit.
723 var files
: nullable Array[GithubFile] = null is optional
, writable
726 var message
: nullable String is writable
728 # Git commit representation linked to this commit.
729 var commit
: nullable GitCommit
732 # A Git Commit representation
738 var sha
: nullable String is writable
740 # Parent commits of `self`.
741 var parents
: nullable Array[GitCommit] = null is writable
743 # Author of the commit.
744 var author
: nullable GitUser is writable
746 # Committer of the commit.
747 var committer
: nullable GitUser is writable
750 var message
: nullable String is writable
753 # Git user authoring data
759 var date
: nullable String = null is writable
761 # Authoring date as ISODate.
762 fun iso_date
: nullable ISODate do
764 if date
== null then return null
765 return new ISODate.from_string
(date
)
771 # Should be accessed from `GithubAPI::load_issue`.
773 # See <https://developer.github.com/v3/issues/>.
779 var number
: Int is writable
782 var id
: nullable Int is writable
785 var title
: String is writable
787 # User that created this issue.
788 var user
: nullable User is writable
790 # List of labels on this issue associated to their names.
791 var labels
: nullable Array[Label] is writable
793 # State of the issue on Github.
794 var state
: String is writable
796 # Is the issue locked?
797 var locked
: nullable Bool is writable
799 # Assigned `User` (if any).
800 var assignee
: nullable User is writable
802 # `Milestone` (if any).
803 var milestone
: nullable Milestone is writable
805 # Number of comments on this issue.
806 var comments
: nullable Int is writable
808 # Creation time as String.
809 var created_at
: String is writable
811 # Creation time as ISODate.
812 fun iso_created_at
: ISODate do
813 return new ISODate.from_string
(created_at
)
816 # Last update time as String (if any).
817 var updated_at
: nullable String is writable
819 # Last update date as ISODate.
820 fun iso_updated_at
: nullable ISODate do
821 var updated_at
= self.updated_at
822 if updated_at
== null then return null
823 return new ISODate.from_string
(updated_at
)
826 # Close time as String (if any).
827 var closed_at
: nullable String is writable
829 # Close time as ISODate.
830 fun iso_closed_at
: nullable ISODate do
831 var closed_at
= self.closed_at
832 if closed_at
== null then return null
833 return new ISODate.from_string
(closed_at
)
836 # Full description of the issue.
837 var body
: nullable String is writable
839 # User that closed this issue (if any).
840 var closed_by
: nullable User is writable
842 # Is this issue linked to a pull request?
843 var is_pull_request
: Bool = false is writable
846 # A Github pull request.
848 # Should be accessed from `GithubAPI::load_pull`.
850 # PullRequest are basically Issues with more data.
851 # See <https://developer.github.com/v3/pulls/>.
856 # Merge time as String (if any).
857 var merged_at
: nullable String is writable
859 # Merge time as ISODate.
860 fun iso_merged_at
: nullable ISODate do
861 var merged_at
= self.merged_at
862 if merged_at
== null then return null
863 return new ISODate.from_string
(merged_at
)
867 var merge_commit_sha
: nullable String is writable
869 # Count of comments made on the pull request diff.
870 var review_comments
: Int is writable
872 # Pull request head (can be a commit SHA or a branch name).
873 var head
: PullRef is writable
875 # Pull request base (can be a commit SHA or a branch name).
876 var base
: PullRef is writable
878 # Is this pull request merged?
879 var merged
: Bool is writable
881 # Is this pull request mergeable?
882 var mergeable
: nullable Bool is writable
884 # Mergeable state of this pull request.
886 # See <https://developer.github.com/v3/pulls/#list-pull-requests>.
887 var mergeable_state
: String is writable
889 # User that merged this pull request (if any).
890 var merged_by
: nullable User is writable
892 # Count of commits in this pull request.
893 var commits
: Int is writable
896 var additions
: Int is writable
898 # Deleted line count.
899 var deletions
: Int is writable
901 # Changed files count.
902 var changed_files
: Int is writable
905 var patch_url
: nullable String is writable
908 # A pull request reference (used for head and base).
912 # Label pointed by `self`.
913 var labl
: String is writable, serialize_as
("label")
915 # Reference pointed by `self`.
916 var ref
: String is writable
918 # Commit SHA pointed by `self`.
919 var sha
: String is writable
921 # User pointed by `self`.
922 var user
: User is writable
924 # Repo pointed by `self` (if any).
926 # A `null` value means the `repo` was deleted.
927 var repo
: nullable Repo is writable
932 # Should be accessed from `GithubAPI::load_label`.
934 # See <https://developer.github.com/v3/issues/labels/>.
940 var name
: String is writable
943 var color
: String is writable
946 # A Github milestone.
948 # Should be accessed from `GithubAPI::load_milestone`.
950 # See <https://developer.github.com/v3/issues/milestones/>.
955 # The milestone id on Github.
956 var number
: nullable Int = null is writable
959 var title
: String is writable
961 # Milestone long description.
962 var description
: nullable String is writable
964 # Count of opened issues linked to this milestone.
965 var open_issues
: nullable Int = null is writable
967 # Count of closed issues linked to this milestone.
968 var closed_issues
: nullable Int = null is writable
971 var state
: nullable String is writable
973 # Creation time as String.
974 var created_at
: nullable String is writable
976 # Creation time as ISODate.
977 fun iso_created_at
: nullable ISODate do
978 var created_at
= self.created_at
979 if created_at
== null then return null
980 return new ISODate.from_string
(created_at
)
983 # User that created this milestone.
984 var creator
: nullable User is writable
986 # Due time as String (if any).
987 var due_on
: nullable String is writable
989 # Due time in ISODate format (if any).
990 fun iso_due_on
: nullable ISODate do
991 var due_on
= self.due_on
992 if due_on
== null then return null
993 return new ISODate.from_string
(due_on
)
996 # Last update time as String (if any).
997 var updated_at
: nullable String is writable
999 # Last update date as ISODate.
1000 fun iso_updated_at
: nullable ISODate do
1001 var updated_at
= self.updated_at
1002 if updated_at
== null then return null
1003 return new ISODate.from_string
(updated_at
)
1006 # Close time as String (if any).
1007 var closed_at
: nullable String is writable
1009 # Close time as ISODate.
1010 fun iso_closed_at
: nullable ISODate do
1011 var closed_at
= self.closed_at
1012 if closed_at
== null then return null
1013 return new ISODate.from_string
(closed_at
)
1019 # There is two kinds of comments:
1021 # * `CommitComment` are made on a commit page.
1022 # * `IssueComment` are made on an issue or pull request page.
1023 # * `ReviewComment` are made on the diff associated to a pull request.
1024 abstract class Comment
1028 # Identifier of this comment.
1029 var id
: Int is writable
1031 # User that made this comment.
1032 var user
: User is writable
1034 # Creation time as String.
1035 var created_at
: String is writable
1037 # Creation time as ISODate.
1038 fun iso_created_at
: nullable ISODate do
1039 return new ISODate.from_string
(created_at
)
1042 # Last update time as String (if any).
1043 var updated_at
: nullable String is writable
1045 # Last update date as ISODate.
1046 fun iso_updated_at
: nullable ISODate do
1047 var updated_at
= self.updated_at
1048 if updated_at
== null then return null
1049 return new ISODate.from_string
(updated_at
)
1052 # Comment body text.
1053 var body
: String is writable
1055 # Does the comment contain an acknowledgement (+1)
1057 return body
.has
("\\+1\\b".to_re
) or body
.has
(":+1:") or body
.has
(":shipit:")
1061 # A comment made on a commit.
1067 var commit_id
: String is writable
1069 # Position of the comment on the line.
1070 var position
: nullable Int is writable
1072 # Line of the comment.
1073 var line
: nullable Int is writable
1075 # Path of the commented file.
1076 var path
: nullable String is writable
1079 # Comments made on Github issue and pull request pages.
1081 # Should be accessed from `GithubAPI::load_issue_comment`.
1083 # See <https://developer.github.com/v3/issues/comments/>.
1088 # Issue that contains `self`.
1089 fun issue_number
: Int do return issue_url
.split
("/").last
.to_i
1091 # Link to the issue document on API.
1092 var issue_url
: String is writable
1095 # Comments made on Github pull request diffs.
1097 # Should be accessed from `GithubAPI::load_diff_comment`.
1099 # See <https://developer.github.com/v3/pulls/comments/>.
1104 # Pull request that contains `self`.
1105 fun pull_number
: Int do return pull_request_url
.split
("/").last
.to_i
1107 # Link to the pull request on API.
1108 var pull_request_url
: String is writable
1111 var diff_hunk
: String is writable
1113 # Path of commented file.
1114 var path
: String is writable
1116 # Position of the comment on the file.
1117 var position
: nullable Int is writable
1119 # Original position in the diff.
1120 var original_position
: Int is writable
1122 # Commit referenced by this comment.
1123 var commit_id
: String is writable
1125 # Original commit id.
1126 var original_commit_id
: String is writable
1129 # An event that occurs on a Github `Issue`.
1131 # Should be accessed from `GithubAPI::load_issue_event`.
1133 # See <https://developer.github.com/v3/issues/events/>.
1138 # Event id on Github.
1139 var id
: Int is writable
1141 # User that initiated the event.
1142 var actor
: User is writable
1144 # Creation time as String.
1145 var created_at
: String is writable
1147 # Creation time as ISODate.
1148 fun iso_created_at
: nullable ISODate do
1149 return new ISODate.from_string
(created_at
)
1153 var event
: String is writable
1155 # Commit linked to this event (if any).
1156 var commit_id
: nullable String is writable
1158 # Label linked to this event (if any).
1159 var labl
: nullable Label is writable, serialize_as
("label")
1161 # User linked to this event (if any).
1162 var assignee
: nullable User is writable
1164 # Milestone linked to this event (if any).
1165 var milestone
: nullable Milestone is writable
1167 # Rename linked to this event (if any).
1168 var rename
: nullable RenameAction is writable
1171 # A rename action maintains the name before and after a renaming action.
1175 # Name before renaming.
1176 var from
: String is writable
1178 # Name after renaming.
1179 var to
: String is writable
1183 # Should be accessed from `Repo::contrib_stats`.
1185 # See <https://developer.github.com/v3/repos/statistics/>.
1186 class ContributorStats
1190 redef type OTHER: ContributorStats
1192 # Github API client.
1193 var api
: GithubAPI is writable
1195 # User these statistics are about.
1196 var author
: User is writable
1198 # Total number of commit.
1199 var total
: Int is writable
1201 # Are of weeks of activity with detailed statistics.
1202 var weeks
: JsonArray is writable
1204 # ContributorStats can be compared on the total amount of commits.
1205 redef fun <(o
) do return total
< o
.total
1208 # A Github file representation.
1210 # Mostly a wrapper around a json object.
1215 var filename
: String is writable
1218 # Make ISO Datew serilizable
1223 # JsonDeserializer specific for Github objects.
1224 class GithubDeserializer
1225 super JsonDeserializer
1227 redef fun class_name_heuristic
(json_object
) do
1228 if json_object
.has_key
("login") then
1230 else if json_object
.has_key
("full_name") then
1232 else if json_object
.has_key
("name") and json_object
.has_key
("commit") then
1234 else if json_object
.has_key
("sha") and json_object
.has_key
("ref") then
1236 else if (json_object
.has_key
("sha") and json_object
.has_key
("commit")) or (json_object
.has_key
("id") and json_object
.has_key
("tree_id")) then
1238 else if json_object
.has_key
("sha") and json_object
.has_key
("tree") then
1240 else if json_object
.has_key
("name") and json_object
.has_key
("date") then
1242 else if json_object
.has_key
("number") and json_object
.has_key
("patch_url") then
1243 return "PullRequest"
1244 else if json_object
.has_key
("open_issues") and json_object
.has_key
("closed_issues") then
1246 else if json_object
.has_key
("number") and json_object
.has_key
("title") then
1248 else if json_object
.has_key
("color") then
1250 else if json_object
.has_key
("event") then
1252 else if json_object
.has_key
("original_commit_id") then
1253 return "ReviewComment"
1254 else if json_object
.has_key
("commit_id") then
1255 return "CommitComment"
1256 else if json_object
.has_key
("issue_url") then
1257 return "IssueComment"
1262 redef fun deserialize_class
(name
) do
1263 if name
== "Issue" then
1264 var issue
= super.as(Issue)
1265 if path
.last
.has_key
("pull_request") then
1266 issue
.is_pull_request
= true
1269 else if name
== "Commit" then
1270 var commit
= super.as(Commit)
1271 var git_commit
= commit
.commit
1272 if git_commit
!= null then commit
.message
= git_commit
.message
1279 # Gets the Github token from `git` configuration
1281 # Return the value of `git config --get github.oauthtoken`
1282 # or `""` if no key exists.
1283 fun get_github_oauth
: String
1285 var p
= new ProcessReader("git", "config", "--get", "github.oauthtoken")
1286 var token
= p
.read_line