gitlab 4.2.0 → 4.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -2
- data/LICENSE.txt +1 -1
- data/README.md +96 -25
- data/exe/gitlab +5 -1
- data/lib/gitlab/api.rb +8 -3
- data/lib/gitlab/cli.rb +15 -15
- data/lib/gitlab/cli_helpers.rb +63 -61
- data/lib/gitlab/client/access_requests.rb +103 -0
- data/lib/gitlab/client/application_settings.rb +172 -0
- data/lib/gitlab/client/avatar.rb +21 -0
- data/lib/gitlab/client/award_emojis.rb +5 -3
- data/lib/gitlab/client/boards.rb +62 -4
- data/lib/gitlab/client/branches.rb +53 -14
- data/lib/gitlab/client/broadcast_messages.rb +75 -0
- data/lib/gitlab/client/build_variables.rb +78 -9
- data/lib/gitlab/client/builds.rb +13 -11
- data/lib/gitlab/client/commits.rb +89 -19
- data/lib/gitlab/client/container_registry.rb +85 -0
- data/lib/gitlab/client/deployments.rb +34 -0
- data/lib/gitlab/client/environments.rb +5 -3
- data/lib/gitlab/client/epic_issues.rb +23 -0
- data/lib/gitlab/client/epics.rb +73 -0
- data/lib/gitlab/client/events.rb +60 -0
- data/lib/gitlab/client/features.rb +48 -0
- data/lib/gitlab/client/group_badges.rb +88 -0
- data/lib/gitlab/client/group_boards.rb +141 -0
- data/lib/gitlab/client/group_labels.rb +88 -0
- data/lib/gitlab/client/group_milestones.rb +94 -0
- data/lib/gitlab/client/groups.rb +197 -17
- data/lib/gitlab/client/issue_links.rb +48 -0
- data/lib/gitlab/client/issues.rb +98 -4
- data/lib/gitlab/client/jobs.rb +96 -8
- data/lib/gitlab/client/keys.rb +13 -0
- data/lib/gitlab/client/labels.rb +7 -5
- data/lib/gitlab/client/lint.rb +19 -0
- data/lib/gitlab/client/markdown.rb +23 -0
- data/lib/gitlab/client/merge_request_approvals.rb +265 -0
- data/lib/gitlab/client/merge_requests.rb +237 -9
- data/lib/gitlab/client/milestones.rb +19 -5
- data/lib/gitlab/client/namespaces.rb +4 -2
- data/lib/gitlab/client/notes.rb +58 -12
- data/lib/gitlab/client/pipeline_schedules.rb +147 -0
- data/lib/gitlab/client/pipeline_triggers.rb +12 -10
- data/lib/gitlab/client/pipelines.rb +40 -3
- data/lib/gitlab/client/project_badges.rb +85 -0
- data/lib/gitlab/client/project_clusters.rb +83 -0
- data/lib/gitlab/client/project_release_links.rb +76 -0
- data/lib/gitlab/client/project_releases.rb +79 -0
- data/lib/gitlab/client/projects.rb +280 -47
- data/lib/gitlab/client/protected_tags.rb +59 -0
- data/lib/gitlab/client/remote_mirrors.rb +51 -0
- data/lib/gitlab/client/repositories.rb +60 -6
- data/lib/gitlab/client/repository_files.rb +23 -5
- data/lib/gitlab/client/repository_submodules.rb +27 -0
- data/lib/gitlab/client/resource_label_events.rb +82 -0
- data/lib/gitlab/client/resource_state_events.rb +57 -0
- data/lib/gitlab/client/runners.rb +111 -15
- data/lib/gitlab/client/search.rb +66 -0
- data/lib/gitlab/client/services.rb +4 -1
- data/lib/gitlab/client/sidekiq.rb +39 -0
- data/lib/gitlab/client/snippets.rb +8 -4
- data/lib/gitlab/client/system_hooks.rb +9 -7
- data/lib/gitlab/client/tags.rb +15 -14
- data/lib/gitlab/client/templates.rb +100 -0
- data/lib/gitlab/client/todos.rb +7 -5
- data/lib/gitlab/client/user_snippets.rb +114 -0
- data/lib/gitlab/client/users.rb +166 -30
- data/lib/gitlab/client/versions.rb +18 -0
- data/lib/gitlab/client/wikis.rb +79 -0
- data/lib/gitlab/client.rb +49 -12
- data/lib/gitlab/configuration.rb +8 -6
- data/lib/gitlab/error.rb +74 -5
- data/lib/gitlab/file_response.rb +5 -3
- data/lib/gitlab/help.rb +19 -20
- data/lib/gitlab/objectified_hash.rb +27 -10
- data/lib/gitlab/page_links.rb +11 -9
- data/lib/gitlab/paginated_response.rb +37 -24
- data/lib/gitlab/request.rb +42 -53
- data/lib/gitlab/shell.rb +11 -12
- data/lib/gitlab/shell_history.rb +11 -13
- data/lib/gitlab/version.rb +3 -1
- data/lib/gitlab.rb +19 -8
- metadata +50 -395
- data/.gitignore +0 -22
- data/.travis.yml +0 -8
- data/CONTRIBUTING.md +0 -195
- data/Gemfile +0 -4
- data/Rakefile +0 -9
- data/bin/console +0 -10
- data/bin/setup +0 -6
- data/gitlab.gemspec +0 -31
- data/spec/fixtures/board_list.json +0 -1
- data/spec/fixtures/board_lists.json +0 -1
- data/spec/fixtures/boards.json +0 -1
- data/spec/fixtures/branch.json +0 -1
- data/spec/fixtures/branch_delete.json +0 -3
- data/spec/fixtures/branches.json +0 -1
- data/spec/fixtures/build.json +0 -38
- data/spec/fixtures/build_artifacts.json +0 -0
- data/spec/fixtures/build_cancel.json +0 -24
- data/spec/fixtures/build_erase.json +0 -24
- data/spec/fixtures/build_retry.json +0 -24
- data/spec/fixtures/builds.json +0 -78
- data/spec/fixtures/builds_commits.json +0 -64
- data/spec/fixtures/compare_merge_request_diff.json +0 -31
- data/spec/fixtures/empty.json +0 -0
- data/spec/fixtures/environment.json +0 -6
- data/spec/fixtures/environments.json +0 -14
- data/spec/fixtures/error_already_exists.json +0 -1
- data/spec/fixtures/error_project_not_found.json +0 -1
- data/spec/fixtures/get_repository_file.json +0 -1
- data/spec/fixtures/group.json +0 -60
- data/spec/fixtures/group_create.json +0 -1
- data/spec/fixtures/group_create_with_description.json +0 -1
- data/spec/fixtures/group_delete.json +0 -1
- data/spec/fixtures/group_member.json +0 -1
- data/spec/fixtures/group_member_delete.json +0 -1
- data/spec/fixtures/group_member_edit.json +0 -1
- data/spec/fixtures/group_members.json +0 -1
- data/spec/fixtures/group_projects.json +0 -44
- data/spec/fixtures/group_search.json +0 -2
- data/spec/fixtures/groups.json +0 -2
- data/spec/fixtures/issue.json +0 -1
- data/spec/fixtures/issue_award_emoji.json +0 -16
- data/spec/fixtures/issue_award_emojis.json +0 -34
- data/spec/fixtures/issues.json +0 -1
- data/spec/fixtures/job.json +0 -43
- data/spec/fixtures/job_trace.json +0 -1
- data/spec/fixtures/jobs.json +0 -91
- data/spec/fixtures/key.json +0 -1
- data/spec/fixtures/keys.json +0 -1
- data/spec/fixtures/label.json +0 -1
- data/spec/fixtures/label_unsubscribe.json +0 -1
- data/spec/fixtures/labels.json +0 -1
- data/spec/fixtures/merge_request.json +0 -1
- data/spec/fixtures/merge_request_award_emoji.json +0 -16
- data/spec/fixtures/merge_request_award_emojis.json +0 -34
- data/spec/fixtures/merge_request_changes.json +0 -1
- data/spec/fixtures/merge_request_closes_issues.json +0 -1
- data/spec/fixtures/merge_request_comment.json +0 -1
- data/spec/fixtures/merge_request_comments.json +0 -1
- data/spec/fixtures/merge_request_commits.json +0 -1
- data/spec/fixtures/merge_requests.json +0 -1
- data/spec/fixtures/milestone.json +0 -1
- data/spec/fixtures/milestone_issues.json +0 -1
- data/spec/fixtures/milestone_merge_requests.json +0 -1
- data/spec/fixtures/milestones.json +0 -1
- data/spec/fixtures/namespaces.json +0 -1
- data/spec/fixtures/note.json +0 -1
- data/spec/fixtures/note_award_emoji.json +0 -16
- data/spec/fixtures/note_award_emojis.json +0 -18
- data/spec/fixtures/notes.json +0 -1
- data/spec/fixtures/pipeline.json +0 -23
- data/spec/fixtures/pipeline_cancel.json +0 -23
- data/spec/fixtures/pipeline_create.json +0 -23
- data/spec/fixtures/pipeline_jobs.json +0 -91
- data/spec/fixtures/pipeline_retry.json +0 -23
- data/spec/fixtures/pipelines.json +0 -48
- data/spec/fixtures/project.json +0 -1
- data/spec/fixtures/project_commit.json +0 -13
- data/spec/fixtures/project_commit_comment.json +0 -1
- data/spec/fixtures/project_commit_comments.json +0 -1
- data/spec/fixtures/project_commit_create.json +0 -22
- data/spec/fixtures/project_commit_diff.json +0 -10
- data/spec/fixtures/project_commit_status.json +0 -42
- data/spec/fixtures/project_commits.json +0 -1
- data/spec/fixtures/project_edit.json +0 -21
- data/spec/fixtures/project_events.json +0 -1
- data/spec/fixtures/project_for_user.json +0 -1
- data/spec/fixtures/project_fork.json +0 -50
- data/spec/fixtures/project_fork_link.json +0 -1
- data/spec/fixtures/project_forked_for_user.json +0 -50
- data/spec/fixtures/project_hook.json +0 -1
- data/spec/fixtures/project_hooks.json +0 -1
- data/spec/fixtures/project_issues.json +0 -1
- data/spec/fixtures/project_key.json +0 -6
- data/spec/fixtures/project_keys.json +0 -6
- data/spec/fixtures/project_runner_enable.json +0 -7
- data/spec/fixtures/project_runners.json +0 -16
- data/spec/fixtures/project_search.json +0 -1
- data/spec/fixtures/project_star.json +0 -44
- data/spec/fixtures/project_tag_annotated.json +0 -1
- data/spec/fixtures/project_tag_lightweight.json +0 -1
- data/spec/fixtures/project_tags.json +0 -1
- data/spec/fixtures/project_unstar.json +0 -44
- data/spec/fixtures/project_update_commit_status.json +0 -20
- data/spec/fixtures/projects.json +0 -1
- data/spec/fixtures/push_rule.json +0 -1
- data/spec/fixtures/raw_file.json +0 -2
- data/spec/fixtures/release_create.json +0 -1
- data/spec/fixtures/release_update.json +0 -1
- data/spec/fixtures/repository_file.json +0 -1
- data/spec/fixtures/run_trigger.json +0 -1
- data/spec/fixtures/runner.json +0 -26
- data/spec/fixtures/runner_delete.json +0 -7
- data/spec/fixtures/runner_edit.json +0 -26
- data/spec/fixtures/runners.json +0 -16
- data/spec/fixtures/runners_all.json +0 -30
- data/spec/fixtures/service.json +0 -1
- data/spec/fixtures/session.json +0 -1
- data/spec/fixtures/shell_history.json +0 -2
- data/spec/fixtures/snippet.json +0 -1
- data/spec/fixtures/snippet_award_emoji.json +0 -16
- data/spec/fixtures/snippet_award_emojis.json +0 -34
- data/spec/fixtures/snippet_content.json +0 -3
- data/spec/fixtures/snippets.json +0 -1
- data/spec/fixtures/system_hook.json +0 -1
- data/spec/fixtures/system_hooks.json +0 -1
- data/spec/fixtures/tag.json +0 -1
- data/spec/fixtures/tag_create.json +0 -1
- data/spec/fixtures/tag_create_with_description.json +0 -1
- data/spec/fixtures/tag_delete.json +0 -1
- data/spec/fixtures/tags.json +0 -1
- data/spec/fixtures/team_member.json +0 -1
- data/spec/fixtures/team_members.json +0 -1
- data/spec/fixtures/todo.json +0 -73
- data/spec/fixtures/todos.json +0 -148
- data/spec/fixtures/tree.json +0 -1
- data/spec/fixtures/trigger.json +0 -10
- data/spec/fixtures/triggers.json +0 -12
- data/spec/fixtures/user.json +0 -1
- data/spec/fixtures/user_block_unblock.json +0 -1
- data/spec/fixtures/user_email.json +0 -1
- data/spec/fixtures/user_emails.json +0 -1
- data/spec/fixtures/user_search.json +0 -1
- data/spec/fixtures/users.json +0 -1
- data/spec/fixtures/variable.json +0 -4
- data/spec/fixtures/variables.json +0 -10
- data/spec/gitlab/cli_helpers_spec.rb +0 -57
- data/spec/gitlab/cli_spec.rb +0 -119
- data/spec/gitlab/client/award_emojis_spec.rb +0 -391
- data/spec/gitlab/client/boards_spec.rb +0 -94
- data/spec/gitlab/client/branches_spec.rb +0 -116
- data/spec/gitlab/client/build_variables_spec.rb +0 -86
- data/spec/gitlab/client/builds_spec.rb +0 -148
- data/spec/gitlab/client/client_spec.rb +0 -11
- data/spec/gitlab/client/commits_spec.rb +0 -168
- data/spec/gitlab/client/environments_spec.rb +0 -132
- data/spec/gitlab/client/groups_spec.rb +0 -195
- data/spec/gitlab/client/issues_spec.rb +0 -186
- data/spec/gitlab/client/jobs_spec.rb +0 -135
- data/spec/gitlab/client/keys_spec.rb +0 -19
- data/spec/gitlab/client/labels_spec.rb +0 -100
- data/spec/gitlab/client/merge_requests_spec.rb +0 -224
- data/spec/gitlab/client/milestones_spec.rb +0 -98
- data/spec/gitlab/client/namespaces_spec.rb +0 -22
- data/spec/gitlab/client/notes_spec.rb +0 -333
- data/spec/gitlab/client/pipeline_triggers_spec.rb +0 -157
- data/spec/gitlab/client/pipelines_spec.rb +0 -95
- data/spec/gitlab/client/projects_spec.rb +0 -613
- data/spec/gitlab/client/repositories_spec.rb +0 -94
- data/spec/gitlab/client/repository_files_spec.rb +0 -95
- data/spec/gitlab/client/runners_spec.rb +0 -185
- data/spec/gitlab/client/services_spec.rb +0 -55
- data/spec/gitlab/client/snippets_spec.rb +0 -100
- data/spec/gitlab/client/system_hooks_spec.rb +0 -69
- data/spec/gitlab/client/tags_spec.rb +0 -109
- data/spec/gitlab/client/todos_spec.rb +0 -45
- data/spec/gitlab/client/users_spec.rb +0 -418
- data/spec/gitlab/error_spec.rb +0 -45
- data/spec/gitlab/file_response_spec.rb +0 -33
- data/spec/gitlab/help_spec.rb +0 -46
- data/spec/gitlab/objectified_hash_spec.rb +0 -48
- data/spec/gitlab/page_links_spec.rb +0 -16
- data/spec/gitlab/paginated_response_spec.rb +0 -60
- data/spec/gitlab/request_spec.rb +0 -73
- data/spec/gitlab/shell_history_spec.rb +0 -53
- data/spec/gitlab/shell_spec.rb +0 -80
- data/spec/gitlab_spec.rb +0 -97
- data/spec/spec_helper.rb +0 -74
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Gitlab::Client
|
|
4
|
+
# Defines methods related to wikis.
|
|
5
|
+
# @see https://docs.gitlab.com/ce/api/wikis.html
|
|
6
|
+
module Wikis
|
|
7
|
+
# Get all wiki pages for a given project.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Gitlab.wikis(3)
|
|
11
|
+
# Gitlab.wikis(3, {with_content: 'Some wiki content'})
|
|
12
|
+
#
|
|
13
|
+
# @param [Integer, String] project The ID or name of a project.
|
|
14
|
+
# @param [Hash] options A customizable set of options.
|
|
15
|
+
# @option options [String] with_content(optional) Include pages content
|
|
16
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
|
17
|
+
def wikis(project, options = {})
|
|
18
|
+
get("/projects/#{url_encode project}/wikis", query: options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Get a wiki page for a given project.
|
|
22
|
+
#
|
|
23
|
+
# @example
|
|
24
|
+
# Gitlab.wiki(3, 'home')
|
|
25
|
+
#
|
|
26
|
+
# @param [Integer, String] project The ID or name of a project.
|
|
27
|
+
# @param [String] slug The slug (a unique string) of the wiki page
|
|
28
|
+
# @return [Gitlab::ObjectifiedHash]
|
|
29
|
+
def wiki(project, slug)
|
|
30
|
+
get("/projects/#{url_encode project}/wikis/#{slug}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates a new wiki page for the given repository with the given title, slug, and content.
|
|
34
|
+
#
|
|
35
|
+
# @example
|
|
36
|
+
# Gitlab.create_wiki(3, 'Some Title', 'Some Content')
|
|
37
|
+
# Gitlab.create_wiki(3, 'Some Title', 'Some Content', { format: 'rdoc' })
|
|
38
|
+
#
|
|
39
|
+
# @param [Integer, String] project The ID or name of a project.
|
|
40
|
+
# @param [String] content The content of the wiki page.
|
|
41
|
+
# @param [String] title The title of the wiki page.
|
|
42
|
+
# @param [Hash] options A customizable set of options.
|
|
43
|
+
# @option options [String] format (optional) The format of the wiki page. Available formats are: markdown (default), rdoc, and asciidoc.
|
|
44
|
+
# @return [Gitlab::ObjectifiedHash] Information about created wiki page.
|
|
45
|
+
def create_wiki(project, title, content, options = {})
|
|
46
|
+
body = { content: content, title: title }.merge(options)
|
|
47
|
+
post("/projects/#{url_encode project}/wikis", body: body)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Updates an existing wiki page. At least one parameter is required to update the wiki page.
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# Gitlab.update_wiki(6, 'home', { title: 'New title' })
|
|
54
|
+
# Gitlab.update_wiki(6, 'home', { title: 'New title', content: 'New Message', format: 'rdoc' })
|
|
55
|
+
#
|
|
56
|
+
# @param [Integer, String] project The ID or name of a project.
|
|
57
|
+
# @param [String] slug The slug (a unique string) of the wiki page.
|
|
58
|
+
# @param [Hash] options A customizable set of options.
|
|
59
|
+
# @option options [String] content The content of the wiki page.
|
|
60
|
+
# @option options [String] title The title of the wiki page.
|
|
61
|
+
# @option options [String] format (optional) The format of the wiki page. Available formats are: markdown (default), rdoc, and asciidoc.
|
|
62
|
+
# @return [Gitlab::ObjectifiedHash] Information about updated wiki page.
|
|
63
|
+
def update_wiki(project, slug, options = {})
|
|
64
|
+
put("/projects/#{url_encode project}/wikis/#{slug}", body: options)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Deletes a wiki page with a given slug.
|
|
68
|
+
#
|
|
69
|
+
# @example
|
|
70
|
+
# Gitlab.delete_wiki(42, 'foo')
|
|
71
|
+
#
|
|
72
|
+
# @param [Integer, String] project The ID or name of a project.
|
|
73
|
+
# @param [String] slug The slug (a unique string) of the wiki page.
|
|
74
|
+
# @return [Gitlab::ObjectifiedHash] An empty objectified hash
|
|
75
|
+
def delete_wiki(project, slug)
|
|
76
|
+
delete("/projects/#{url_encode project}/wikis/#{slug}")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/gitlab/client.rb
CHANGED
|
@@ -1,58 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
# Wrapper for the Gitlab REST API.
|
|
3
5
|
class Client < API
|
|
4
|
-
Dir[File.expand_path('
|
|
6
|
+
Dir[File.expand_path('client/*.rb', __dir__)].each { |f| require f }
|
|
5
7
|
|
|
8
|
+
# Please keep in alphabetical order
|
|
9
|
+
include AccessRequests
|
|
10
|
+
include ApplicationSettings
|
|
11
|
+
include Avatar
|
|
6
12
|
include AwardEmojis
|
|
7
13
|
include Boards
|
|
8
14
|
include Branches
|
|
9
|
-
include
|
|
15
|
+
include BroadcastMessages
|
|
10
16
|
include BuildVariables
|
|
17
|
+
include Builds
|
|
11
18
|
include Commits
|
|
19
|
+
include ContainerRegistry
|
|
20
|
+
include Deployments
|
|
12
21
|
include Environments
|
|
22
|
+
include EpicIssues
|
|
23
|
+
include Epics
|
|
24
|
+
include Events
|
|
25
|
+
include Features
|
|
26
|
+
include GroupBadges
|
|
27
|
+
include GroupBoards
|
|
28
|
+
include GroupLabels
|
|
29
|
+
include GroupMilestones
|
|
13
30
|
include Groups
|
|
31
|
+
include IssueLinks
|
|
14
32
|
include Issues
|
|
33
|
+
include Jobs
|
|
15
34
|
include Keys
|
|
16
35
|
include Labels
|
|
36
|
+
include Lint
|
|
37
|
+
include Markdown
|
|
38
|
+
include MergeRequestApprovals
|
|
17
39
|
include MergeRequests
|
|
18
40
|
include Milestones
|
|
19
41
|
include Namespaces
|
|
20
42
|
include Notes
|
|
21
|
-
include
|
|
43
|
+
include PipelineSchedules
|
|
22
44
|
include PipelineTriggers
|
|
45
|
+
include Pipelines
|
|
46
|
+
include ProjectBadges
|
|
47
|
+
include ProjectClusters
|
|
48
|
+
include ProjectReleaseLinks
|
|
49
|
+
include ProjectReleases
|
|
23
50
|
include Projects
|
|
51
|
+
include ProtectedTags
|
|
52
|
+
include RemoteMirrors
|
|
24
53
|
include Repositories
|
|
25
54
|
include RepositoryFiles
|
|
55
|
+
include RepositorySubmodules
|
|
56
|
+
include ResourceLabelEvents
|
|
57
|
+
include ResourceStateEvents
|
|
26
58
|
include Runners
|
|
59
|
+
include Search
|
|
27
60
|
include Services
|
|
61
|
+
include Sidekiq
|
|
28
62
|
include Snippets
|
|
29
63
|
include SystemHooks
|
|
30
64
|
include Tags
|
|
65
|
+
include Templates
|
|
31
66
|
include Todos
|
|
32
67
|
include Users
|
|
33
|
-
include
|
|
68
|
+
include UserSnippets
|
|
69
|
+
include Versions
|
|
70
|
+
include Wikis
|
|
34
71
|
|
|
35
72
|
# Text representation of the client, masking private token.
|
|
36
73
|
#
|
|
37
74
|
# @return [String]
|
|
38
75
|
def inspect
|
|
39
76
|
inspected = super
|
|
40
|
-
|
|
41
|
-
if @private_token
|
|
42
|
-
inspected = inspected.sub! @private_token, only_show_last_four_chars(@private_token)
|
|
43
|
-
end
|
|
44
|
-
|
|
77
|
+
inspected.sub! @private_token, only_show_last_four_chars(@private_token) if @private_token
|
|
45
78
|
inspected
|
|
46
79
|
end
|
|
47
80
|
|
|
48
|
-
|
|
49
|
-
|
|
81
|
+
# Utility method for URL encoding of a string.
|
|
82
|
+
# Copied from https://ruby-doc.org/stdlib-2.7.0/libdoc/erb/rdoc/ERB/Util.html
|
|
83
|
+
#
|
|
84
|
+
# @return [String]
|
|
85
|
+
def url_encode(url)
|
|
86
|
+
url.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m| sprintf('%%%02X', m.unpack1('C')) } # rubocop:disable Style/FormatString
|
|
50
87
|
end
|
|
51
88
|
|
|
52
89
|
private
|
|
53
90
|
|
|
54
91
|
def only_show_last_four_chars(token)
|
|
55
|
-
"#{'*'*(token.size - 4)}#{token[-4..-1]}"
|
|
92
|
+
"#{'*' * (token.size - 4)}#{token[-4..-1]}"
|
|
56
93
|
end
|
|
57
94
|
end
|
|
58
95
|
end
|
data/lib/gitlab/configuration.rb
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'gitlab/cli_helpers'
|
|
2
4
|
module Gitlab
|
|
3
5
|
# Defines constants and methods related to configuration.
|
|
4
6
|
module Configuration
|
|
5
7
|
# An array of valid keys in the options hash when configuring a Gitlab::API.
|
|
6
|
-
VALID_OPTIONS_KEYS = [
|
|
8
|
+
VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httparty].freeze
|
|
7
9
|
|
|
8
10
|
# The user agent that will be sent to the API endpoint if none is set.
|
|
9
|
-
DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}"
|
|
11
|
+
DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}"
|
|
10
12
|
|
|
11
13
|
# @private
|
|
12
14
|
attr_accessor(*VALID_OPTIONS_KEYS)
|
|
13
15
|
# @private
|
|
14
|
-
|
|
16
|
+
alias auth_token= private_token=
|
|
15
17
|
|
|
16
18
|
# Sets all configuration options to their default values
|
|
17
19
|
# when this module is extended.
|
|
@@ -33,7 +35,7 @@ module Gitlab
|
|
|
33
35
|
|
|
34
36
|
# Resets all configuration options to the defaults.
|
|
35
37
|
def reset
|
|
36
|
-
self.endpoint = ENV['GITLAB_API_ENDPOINT']
|
|
38
|
+
self.endpoint = ENV['GITLAB_API_ENDPOINT'] || ENV['CI_API_V4_URL']
|
|
37
39
|
self.private_token = ENV['GITLAB_API_PRIVATE_TOKEN'] || ENV['GITLAB_API_AUTH_TOKEN']
|
|
38
40
|
self.httparty = get_httparty_config(ENV['GITLAB_API_HTTPARTY_OPTIONS'])
|
|
39
41
|
self.sudo = nil
|
|
@@ -44,11 +46,11 @@ module Gitlab
|
|
|
44
46
|
|
|
45
47
|
# Allows HTTParty config to be specified in ENV using YAML hash.
|
|
46
48
|
def get_httparty_config(options)
|
|
47
|
-
return
|
|
49
|
+
return if options.nil?
|
|
48
50
|
|
|
49
51
|
httparty = Gitlab::CLI::Helpers.yaml_load(options)
|
|
52
|
+
raise ArgumentError, 'HTTParty config should be a Hash.' unless httparty.is_a? Hash
|
|
50
53
|
|
|
51
|
-
raise ArgumentError, "HTTParty config should be a Hash." unless httparty.is_a? Hash
|
|
52
54
|
Gitlab::CLI::Helpers.symbolize_keys httparty
|
|
53
55
|
end
|
|
54
56
|
end
|
data/lib/gitlab/error.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
module Error
|
|
3
5
|
# Custom error class for rescuing from all Gitlab errors.
|
|
@@ -11,38 +13,83 @@ module Gitlab
|
|
|
11
13
|
|
|
12
14
|
# Custom error class for rescuing from HTTP response errors.
|
|
13
15
|
class ResponseError < Error
|
|
16
|
+
POSSIBLE_MESSAGE_KEYS = %i[message error_description error].freeze
|
|
17
|
+
|
|
14
18
|
def initialize(response)
|
|
15
19
|
@response = response
|
|
16
20
|
super(build_error_message)
|
|
17
21
|
end
|
|
18
22
|
|
|
19
|
-
# Status code returned in the
|
|
23
|
+
# Status code returned in the HTTP response.
|
|
20
24
|
#
|
|
21
25
|
# @return [Integer]
|
|
22
26
|
def response_status
|
|
23
27
|
@response.code
|
|
24
28
|
end
|
|
25
29
|
|
|
30
|
+
# Body content returned in the HTTP response
|
|
31
|
+
#
|
|
32
|
+
# @return [String]
|
|
33
|
+
def response_message
|
|
34
|
+
@response.parsed_response.message
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Additional error context returned by some API endpoints
|
|
38
|
+
#
|
|
39
|
+
# @return [String]
|
|
40
|
+
def error_code
|
|
41
|
+
if @response.respond_to?(:error_code)
|
|
42
|
+
@response.error_code
|
|
43
|
+
else
|
|
44
|
+
''
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
26
48
|
private
|
|
27
49
|
|
|
28
50
|
# Human friendly message.
|
|
29
51
|
#
|
|
30
52
|
# @return [String]
|
|
31
53
|
def build_error_message
|
|
32
|
-
parsed_response =
|
|
33
|
-
message = parsed_response
|
|
34
|
-
|
|
54
|
+
parsed_response = classified_response
|
|
55
|
+
message = check_error_keys(parsed_response)
|
|
35
56
|
"Server responded with code #{@response.code}, message: " \
|
|
36
57
|
"#{handle_message(message)}. " \
|
|
37
58
|
"Request URI: #{@response.request.base_uri}#{@response.request.path}"
|
|
38
59
|
end
|
|
39
60
|
|
|
61
|
+
# Error keys vary across the API, find the first key that the parsed_response
|
|
62
|
+
# object responds to and return that, otherwise return the original.
|
|
63
|
+
def check_error_keys(resp)
|
|
64
|
+
key = POSSIBLE_MESSAGE_KEYS.find { |k| resp.respond_to?(k) }
|
|
65
|
+
key ? resp.send(key) : resp
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Parse the body based on the classification of the body content type
|
|
69
|
+
#
|
|
70
|
+
# @return parsed response
|
|
71
|
+
def classified_response
|
|
72
|
+
if @response.respond_to?('headers')
|
|
73
|
+
@response.headers['content-type'] == 'text/plain' ? { message: @response.to_s } : @response.parsed_response
|
|
74
|
+
else
|
|
75
|
+
@response.parsed_response
|
|
76
|
+
end
|
|
77
|
+
rescue Gitlab::Error::Parsing
|
|
78
|
+
# Return stringified response when receiving a
|
|
79
|
+
# parsing error to avoid obfuscation of the
|
|
80
|
+
# api error.
|
|
81
|
+
#
|
|
82
|
+
# note: The Gitlab API does not always return valid
|
|
83
|
+
# JSON when there are errors.
|
|
84
|
+
@response.to_s
|
|
85
|
+
end
|
|
86
|
+
|
|
40
87
|
# Handle error response message in case of nested hashes
|
|
41
88
|
def handle_message(message)
|
|
42
89
|
case message
|
|
43
90
|
when Gitlab::ObjectifiedHash
|
|
44
91
|
message.to_h.sort.map do |key, val|
|
|
45
|
-
"'#{key}' #{(val.is_a?(Hash) ? val.sort.map { |k, v| "(#{k}: #{v.join(' ')})" } : val).join(' ')}"
|
|
92
|
+
"'#{key}' #{(val.is_a?(Hash) ? val.sort.map { |k, v| "(#{k}: #{v.join(' ')})" } : [val].flatten).join(' ')}"
|
|
46
93
|
end.join(', ')
|
|
47
94
|
when Array
|
|
48
95
|
message.join(' ')
|
|
@@ -67,12 +114,18 @@ module Gitlab
|
|
|
67
114
|
# Raised when API endpoint returns the HTTP status code 405.
|
|
68
115
|
class MethodNotAllowed < ResponseError; end
|
|
69
116
|
|
|
117
|
+
# Raised when API endpoint returns the HTTP status code 406.
|
|
118
|
+
class NotAcceptable < ResponseError; end
|
|
119
|
+
|
|
70
120
|
# Raised when API endpoint returns the HTTP status code 409.
|
|
71
121
|
class Conflict < ResponseError; end
|
|
72
122
|
|
|
73
123
|
# Raised when API endpoint returns the HTTP status code 422.
|
|
74
124
|
class Unprocessable < ResponseError; end
|
|
75
125
|
|
|
126
|
+
# Raised when API endpoint returns the HTTP status code 429.
|
|
127
|
+
class TooManyRequests < ResponseError; end
|
|
128
|
+
|
|
76
129
|
# Raised when API endpoint returns the HTTP status code 500.
|
|
77
130
|
class InternalServerError < ResponseError; end
|
|
78
131
|
|
|
@@ -81,5 +134,21 @@ module Gitlab
|
|
|
81
134
|
|
|
82
135
|
# Raised when API endpoint returns the HTTP status code 503.
|
|
83
136
|
class ServiceUnavailable < ResponseError; end
|
|
137
|
+
|
|
138
|
+
# HTTP status codes mapped to error classes.
|
|
139
|
+
STATUS_MAPPINGS = {
|
|
140
|
+
400 => BadRequest,
|
|
141
|
+
401 => Unauthorized,
|
|
142
|
+
403 => Forbidden,
|
|
143
|
+
404 => NotFound,
|
|
144
|
+
405 => MethodNotAllowed,
|
|
145
|
+
406 => NotAcceptable,
|
|
146
|
+
409 => Conflict,
|
|
147
|
+
422 => Unprocessable,
|
|
148
|
+
429 => TooManyRequests,
|
|
149
|
+
500 => InternalServerError,
|
|
150
|
+
502 => BadGateway,
|
|
151
|
+
503 => ServiceUnavailable
|
|
152
|
+
}.freeze
|
|
84
153
|
end
|
|
85
154
|
end
|
data/lib/gitlab/file_response.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
# Wrapper class of file response.
|
|
3
5
|
class FileResponse
|
|
4
|
-
HEADER_CONTENT_DISPOSITION = 'Content-Disposition'
|
|
6
|
+
HEADER_CONTENT_DISPOSITION = 'Content-Disposition'
|
|
5
7
|
|
|
6
8
|
attr_reader :filename
|
|
7
9
|
|
|
@@ -18,7 +20,7 @@ module Gitlab
|
|
|
18
20
|
def to_hash
|
|
19
21
|
{ filename: @filename, data: @file }
|
|
20
22
|
end
|
|
21
|
-
|
|
23
|
+
alias to_h to_hash
|
|
22
24
|
|
|
23
25
|
# @return [String] Formatted string with the class name, object id and filename.
|
|
24
26
|
def inspect
|
|
@@ -39,7 +41,7 @@ module Gitlab
|
|
|
39
41
|
|
|
40
42
|
# Parse filename from the 'Content Disposition' header.
|
|
41
43
|
def parse_headers!(headers)
|
|
42
|
-
@filename = headers[HEADER_CONTENT_DISPOSITION].split(
|
|
44
|
+
@filename = headers[HEADER_CONTENT_DISPOSITION].split('filename=')[1]
|
|
43
45
|
@filename = @filename[1...-1] if @filename[0] == '"' # Unquote filenames
|
|
44
46
|
end
|
|
45
47
|
end
|
data/lib/gitlab/help.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'gitlab'
|
|
2
4
|
require 'gitlab/cli_helpers'
|
|
3
5
|
|
|
@@ -32,9 +34,7 @@ module Gitlab::Help
|
|
|
32
34
|
# @return [String]
|
|
33
35
|
def ri_cmd
|
|
34
36
|
which_ri = `which ri`.chomp
|
|
35
|
-
if which_ri.empty?
|
|
36
|
-
fail "'ri' tool not found in $PATH. Please install it to use the help."
|
|
37
|
-
end
|
|
37
|
+
raise "'ri' tool not found in $PATH. Please install it to use the help." if which_ri.empty?
|
|
38
38
|
|
|
39
39
|
which_ri
|
|
40
40
|
end
|
|
@@ -45,23 +45,22 @@ module Gitlab::Help
|
|
|
45
45
|
#
|
|
46
46
|
# @return [Hash<Array>]
|
|
47
47
|
def help_map
|
|
48
|
-
@help_map ||=
|
|
48
|
+
@help_map ||=
|
|
49
49
|
actions.each_with_object({}) do |action, hsh|
|
|
50
|
-
key = client.method(action)
|
|
51
|
-
|
|
50
|
+
key = client.method(action)
|
|
51
|
+
.owner.to_s.gsub(/Gitlab::(?:Client::)?/, '')
|
|
52
52
|
hsh[key] ||= []
|
|
53
53
|
hsh[key] << action.to_s
|
|
54
54
|
end
|
|
55
|
-
end
|
|
56
55
|
end
|
|
57
56
|
|
|
58
57
|
# Table with available commands.
|
|
59
58
|
#
|
|
60
59
|
# @return [Terminal::Table]
|
|
61
|
-
def actions_table(topic=nil)
|
|
60
|
+
def actions_table(topic = nil)
|
|
62
61
|
rows = topic ? help_map[topic] : help_map.keys
|
|
63
62
|
table do |t|
|
|
64
|
-
t.title = topic ||
|
|
63
|
+
t.title = topic || 'Help Topics'
|
|
65
64
|
|
|
66
65
|
# add_row expects an array and we have strings hence the map.
|
|
67
66
|
rows.sort.map { |r| [r] }.each_with_index do |row, index|
|
|
@@ -73,23 +72,23 @@ module Gitlab::Help
|
|
|
73
72
|
|
|
74
73
|
# Returns full namespace of a command (e.g. Gitlab::Client::Branches.cmd)
|
|
75
74
|
def namespace(cmd)
|
|
76
|
-
method_owners.select { |method| method[:name]
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
method_owners.select { |method| method[:name] == cmd }
|
|
76
|
+
.map { |method| "#{method[:owner]}.#{method[:name]}" }
|
|
77
|
+
.shift
|
|
79
78
|
end
|
|
80
79
|
|
|
81
80
|
# Massage output from 'ri'.
|
|
82
81
|
def change_help_output!(cmd, output_str)
|
|
83
|
-
output_str
|
|
84
|
-
output_str.gsub!(
|
|
85
|
-
|
|
82
|
+
output_str = +output_str
|
|
83
|
+
output_str.gsub!(/#{cmd}(\(.*?\))/m, "#{cmd}\\1")
|
|
84
|
+
output_str.gsub!(/,\s*/, ', ')
|
|
85
|
+
|
|
86
86
|
# Ensure @option descriptions are on a single line
|
|
87
87
|
output_str.gsub!(/\n\[/, " \[")
|
|
88
88
|
output_str.gsub!(/\s(@)/, "\n@")
|
|
89
|
-
output_str.gsub!(/(\])\n(
|
|
90
|
-
output_str.gsub!(/(
|
|
91
|
-
output_str.gsub!(/\{(.+)\}/, '"{
|
|
92
|
-
|
|
89
|
+
output_str.gsub!(/(\])\n(:)/, '\\1 \\2')
|
|
90
|
+
output_str.gsub!(/(:.*)(\n)(.*\.)/, '\\1 \\3')
|
|
91
|
+
output_str.gsub!(/\{(.+)\}/, '"{\\1}"')
|
|
93
92
|
end
|
|
94
|
-
end
|
|
93
|
+
end
|
|
95
94
|
end
|
|
@@ -1,34 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
# Converts hashes to the objects.
|
|
3
5
|
class ObjectifiedHash
|
|
4
6
|
# Creates a new ObjectifiedHash object.
|
|
5
7
|
def initialize(hash)
|
|
6
8
|
@hash = hash
|
|
7
|
-
@data = hash.
|
|
8
|
-
value =
|
|
9
|
+
@data = hash.each_with_object({}) do |(key, value), data|
|
|
10
|
+
value = self.class.new(value) if value.is_a? Hash
|
|
11
|
+
value = value.map { |v| v.is_a?(Hash) ? self.class.new(v) : v } if value.is_a? Array
|
|
9
12
|
data[key.to_s] = value
|
|
10
|
-
data
|
|
11
13
|
end
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
# @return [Hash] The original hash.
|
|
15
17
|
def to_hash
|
|
16
|
-
|
|
18
|
+
hash
|
|
17
19
|
end
|
|
18
|
-
|
|
20
|
+
alias to_h to_hash
|
|
19
21
|
|
|
20
22
|
# @return [String] Formatted string with the class name, object id and original hash.
|
|
21
23
|
def inspect
|
|
22
|
-
"#<#{self.class}:#{object_id} {hash: #{
|
|
24
|
+
"#<#{self.class}:#{object_id} {hash: #{hash.inspect}}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def [](key)
|
|
28
|
+
data[key]
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :hash, :data
|
|
34
|
+
|
|
35
|
+
# Respond to messages for which `self.data` has a key
|
|
36
|
+
def method_missing(method_name, *args, &block)
|
|
37
|
+
if data.key?(method_name.to_s)
|
|
38
|
+
data[method_name.to_s]
|
|
39
|
+
elsif data.respond_to?(method_name)
|
|
40
|
+
warn 'WARNING: Please convert ObjectifiedHash object to hash before calling Hash methods on it.'
|
|
41
|
+
data.send(method_name, *args, &block)
|
|
42
|
+
else
|
|
43
|
+
super
|
|
44
|
+
end
|
|
28
45
|
end
|
|
29
46
|
|
|
30
47
|
def respond_to_missing?(method_name, include_private = false)
|
|
31
|
-
|
|
48
|
+
hash.keys.map(&:to_sym).include?(method_name.to_sym) || super
|
|
32
49
|
end
|
|
33
50
|
end
|
|
34
51
|
end
|
data/lib/gitlab/page_links.rb
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
# Parses link header.
|
|
3
5
|
#
|
|
4
6
|
# @private
|
|
5
7
|
class PageLinks
|
|
6
|
-
HEADER_LINK = 'Link'
|
|
7
|
-
DELIM_LINKS = ','
|
|
8
|
-
LINK_REGEX = /<([^>]+)>; rel
|
|
9
|
-
METAS = %w
|
|
8
|
+
HEADER_LINK = 'Link'
|
|
9
|
+
DELIM_LINKS = ','
|
|
10
|
+
LINK_REGEX = /<([^>]+)>; rel="([^"]+)"/.freeze
|
|
11
|
+
METAS = %w[last next first prev].freeze
|
|
10
12
|
|
|
11
13
|
attr_accessor(*METAS)
|
|
12
14
|
|
|
13
15
|
def initialize(headers)
|
|
14
16
|
link_header = headers[HEADER_LINK]
|
|
15
17
|
|
|
16
|
-
if link_header && link_header =~ /(next|first|last|prev)/
|
|
17
|
-
extract_links(link_header)
|
|
18
|
-
end
|
|
18
|
+
extract_links(link_header) if link_header && link_header =~ /(next|first|last|prev)/
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
private
|
|
@@ -23,9 +23,11 @@ module Gitlab
|
|
|
23
23
|
def extract_links(header)
|
|
24
24
|
header.split(DELIM_LINKS).each do |link|
|
|
25
25
|
LINK_REGEX.match(link.strip) do |match|
|
|
26
|
-
url
|
|
26
|
+
url = match[1]
|
|
27
|
+
meta = match[2]
|
|
27
28
|
next if !url || !meta || METAS.index(meta).nil?
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
send("#{meta}=", url)
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Gitlab
|
|
2
4
|
# Wrapper class of paginated response.
|
|
3
5
|
class PaginatedResponse
|
|
@@ -40,58 +42,69 @@ module Gitlab
|
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
def
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
def lazy_paginate
|
|
46
|
+
to_enum(:each_page).lazy.flat_map(&:to_ary)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def auto_paginate(&block)
|
|
50
|
+
return lazy_paginate.to_a unless block
|
|
51
|
+
|
|
52
|
+
lazy_paginate.each(&block)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def paginate_with_limit(limit, &block)
|
|
56
|
+
return lazy_paginate.take(limit).to_a unless block
|
|
57
|
+
|
|
58
|
+
lazy_paginate.take(limit).each(&block)
|
|
55
59
|
end
|
|
56
60
|
|
|
57
|
-
def
|
|
61
|
+
def last_page?
|
|
58
62
|
!(@links.nil? || @links.last.nil?)
|
|
59
63
|
end
|
|
64
|
+
alias has_last_page? last_page?
|
|
60
65
|
|
|
61
66
|
def last_page
|
|
62
67
|
return nil if @client.nil? || !has_last_page?
|
|
63
|
-
|
|
64
|
-
@client.get(
|
|
68
|
+
|
|
69
|
+
@client.get(client_relative_path(@links.last))
|
|
65
70
|
end
|
|
66
71
|
|
|
67
|
-
def
|
|
72
|
+
def first_page?
|
|
68
73
|
!(@links.nil? || @links.first.nil?)
|
|
69
74
|
end
|
|
75
|
+
alias has_first_page? first_page?
|
|
70
76
|
|
|
71
77
|
def first_page
|
|
72
78
|
return nil if @client.nil? || !has_first_page?
|
|
73
|
-
|
|
74
|
-
@client.get(
|
|
79
|
+
|
|
80
|
+
@client.get(client_relative_path(@links.first))
|
|
75
81
|
end
|
|
76
82
|
|
|
77
|
-
def
|
|
83
|
+
def next_page?
|
|
78
84
|
!(@links.nil? || @links.next.nil?)
|
|
79
85
|
end
|
|
86
|
+
alias has_next_page? next_page?
|
|
80
87
|
|
|
81
88
|
def next_page
|
|
82
89
|
return nil if @client.nil? || !has_next_page?
|
|
83
|
-
|
|
84
|
-
@client.get(
|
|
90
|
+
|
|
91
|
+
@client.get(client_relative_path(@links.next))
|
|
85
92
|
end
|
|
86
93
|
|
|
87
|
-
def
|
|
94
|
+
def prev_page?
|
|
88
95
|
!(@links.nil? || @links.prev.nil?)
|
|
89
96
|
end
|
|
97
|
+
alias has_prev_page? prev_page?
|
|
90
98
|
|
|
91
99
|
def prev_page
|
|
92
100
|
return nil if @client.nil? || !has_prev_page?
|
|
93
|
-
|
|
94
|
-
@client.get(
|
|
101
|
+
|
|
102
|
+
@client.get(client_relative_path(@links.prev))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def client_relative_path(link)
|
|
106
|
+
client_endpoint_path = URI.parse(@client.endpoint).request_uri # api/v4
|
|
107
|
+
URI.parse(link).request_uri.sub(client_endpoint_path, '')
|
|
95
108
|
end
|
|
96
109
|
end
|
|
97
110
|
end
|