Module: TreeHelper

Constant Summary collapse

FILE_LIMIT =
1_000

Instance Method Summary collapse

Methods included from WebIdeButtonHelper

#can_collaborate?, #can_create_mr_from_fork?, #can_push_code?, #edit_url, #fork?, #gitpod_url, #needs_to_fork?, #project_fork, #project_to_use, #readable_blob?, #show_edit_button?, #show_gitpod_button?, #show_web_ide_button?, #web_ide_url

Methods included from BlobHelper

#blob_editor_paths, #blob_icon, #blob_raw_path, #blob_raw_url, #blob_render_error_options, #blob_render_error_reason, #can_modify_blob?, #contribution_options, #copy_blob_source_button, #copy_file_path_button, #delete_blob_link, #dockerfile_names, #download_blob_button, #edit_blob_button, #edit_blob_fork_params, #edit_blob_path, #edit_button_tag, #edit_disabled_button_tag, #edit_fork_button_tag, #edit_link_tag, #edit_modify_file_fork_params, #editing_ci_config?, #editing_preview_title, #encode_ide_path, #fork_and_edit_path, #fork_path_for_current_user, #gitignore_names, #gitlab_ci_ymls, #human_access, #ide_edit_button, #ide_edit_path, #ide_fork_and_edit_path, #ide_merge_request_path, #leave_edit_message, #licenses_for_select, #metrics_dashboard_ymls, #modify_file_button, #no_highlight_files, #open_raw_blob_button, #readable_blob, #ref_project, #replace_blob_link, #sanitize_svg_data, #show_suggest_pipeline_creation_celebration?, #suggest_pipeline_commit_cookie_name

Instance Method Details


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'app/helpers/tree_helper.rb', line 177

def breadcrumb_data_attributes
  attrs = {
    can_collaborate: can_collaborate_with_project?(@project).to_s,
    new_blob_path: project_new_blob_path(@project, @ref),
    upload_path: project_create_blob_path(@project, @ref),
    new_dir_path: project_create_dir_path(@project, @ref),
    new_branch_path: new_project_branch_path(@project),
    new_tag_path: new_project_tag_path(@project),
    can_edit_tree: can_edit_tree?.to_s
  }

  if can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
    continue_param = {
      to: project_new_blob_path(@project, @id),
      notice: edit_in_new_fork_notice,
      notice_now: edit_in_new_fork_notice_now
    }

    attrs.merge!(
      fork_new_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param),
      fork_new_directory_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
        to: request.fullpath,
        notice: _("%{edit_in_new_fork_notice} Try to create a new directory again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
      })),
      fork_upload_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
        to: request.fullpath,
        notice: _("%{edit_in_new_fork_notice} Try to upload a file again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
      }))
    )
  end

  attrs
end

#can_edit_tree?(project = nil, ref = nil) ⇒ Boolean

Returns:

  • (Boolean)

63
64
65
66
67
68
69
70
# File 'app/helpers/tree_helper.rb', line 63

def can_edit_tree?(project = nil, ref = nil)
  project ||= @project
  ref ||= @ref

  return false unless on_top_of_branch?(project, ref)

  can_collaborate_with_project?(project, ref: ref)
end

#commit_in_fork_helpObject


121
122
123
# File 'app/helpers/tree_helper.rb', line 121

def commit_in_fork_help
  _("A new branch will be created in your fork and a new merge request will be started.")
end

#commit_in_single_accessible_branchObject


125
126
127
128
129
130
131
132
# File 'app/helpers/tree_helper.rb', line 125

def commit_in_single_accessible_branch
  branch_name = ERB::Util.html_escape(selected_branch)

  message = _("Your changes can be committed to %{branch_name} because a merge "\
              "request is open.") % { branch_name: "<strong>#{branch_name}</strong>" }

  message.html_safe
end

241
242
243
244
245
246
247
248
# File 'app/helpers/tree_helper.rb', line 241

def directory_download_links(project, ref, archive_prefix)
  Gitlab::Workhorse::ARCHIVE_FORMATS.map do |fmt|
    {
      text: fmt,
      path: project_archive_path(project, id: tree_join(ref, archive_prefix), format: fmt)
    }
  end
end

#edit_in_new_fork_noticeObject


112
113
114
115
# File 'app/helpers/tree_helper.rb', line 112

def edit_in_new_fork_notice
  _("You're not allowed to make changes to this project directly. "\
    "A fork of this project has been created that you can make changes in, so you can submit a merge request.")
end

#edit_in_new_fork_notice_action(action) ⇒ Object


117
118
119
# File 'app/helpers/tree_helper.rb', line 117

def edit_in_new_fork_notice_action(action)
  edit_in_new_fork_notice + _(" Try to %{action} this file again.") % { action: action }
end

#edit_in_new_fork_notice_nowObject


107
108
109
110
# File 'app/helpers/tree_helper.rb', line 107

def edit_in_new_fork_notice_now
  _("You're not allowed to make changes to this project directly. "\
    "A fork of this project is being created that you can make changes in, so you can submit a merge request.")
end

#fast_project_blob_path(project, blob_path) ⇒ Object

Using Rails `*_path` methods can be slow, especially when generating many paths, as with a repository tree that has thousands of items.


42
43
44
45
46
# File 'app/helpers/tree_helper.rb', line 42

def fast_project_blob_path(project, blob_path)
  ActionDispatch::Journey::Router::Utils.escape_path(
    File.join(relative_url_root, project.path_with_namespace, '-', 'blob', blob_path)
  )
end

#fast_project_tree_path(project, tree_path) ⇒ Object


48
49
50
51
52
# File 'app/helpers/tree_helper.rb', line 48

def fast_project_tree_path(project, tree_path)
  ActionDispatch::Journey::Router::Utils.escape_path(
    File.join(relative_url_root, project.path_with_namespace, '-', 'tree', tree_path)
  )
end

#flatten_tree(root_path, tree) ⇒ Object

returns the relative path of the first subdir that doesn't have only one directory descendant


158
159
160
# File 'app/helpers/tree_helper.rb', line 158

def flatten_tree(root_path, tree)
  tree.flat_path.sub(%r{\A#{Regexp.escape(root_path)}/}, '')
end

#on_top_of_branch?(project = @project, ref = @ref) ⇒ Boolean

Returns:

  • (Boolean)

59
60
61
# File 'app/helpers/tree_helper.rb', line 59

def on_top_of_branch?(project = @project, ref = @ref)
  project.repository.branch_exists?(ref)
end

#patch_branch_name(ref) ⇒ Object

Generate a patch branch name that should look like: `username-branchname-patch-epoch` where `epoch` is the last 5 digits of the time since epoch (in milliseconds)

Note: this correlates with how the WebIDE formats the branch name and if this implementation changes, so should the `placeholderBranchName` definition in app/assets/javascripts/ide/stores/modules/commit/getters.js


90
91
92
93
94
95
96
97
# File 'app/helpers/tree_helper.rb', line 90

def patch_branch_name(ref)
  return unless current_user

  username = current_user.username
  epoch = time_in_milliseconds.to_s.last(5)

  "#{username}-#{ref}-patch-#{epoch}"
end

#path_breadcrumbs(max_links = 6) ⇒ Object


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/helpers/tree_helper.rb', line 134

def path_breadcrumbs(max_links = 6)
  if @path.present?
    part_path = ""
    parts = @path.split('/')

    yield('..', File.join(*parts.first(parts.count - 2))) if parts.count > max_links

    parts.each do |part|
      part_path = File.join(part_path, part) unless part_path.empty?
      part_path = part if part_path.empty?

      next if parts.count > max_links && !parts.last(2).include?(part)

      yield(part, part_path)
    end
  end
end

#relative_url_rootObject


166
167
168
# File 'app/helpers/tree_helper.rb', line 166

def relative_url_root
  Gitlab.config.gitlab.relative_url_root.presence || '/'
end

#render_tree(tree) ⇒ Object

Sorts a repository's tree so that folders are before files and renders their corresponding partials

tree - A `Tree` object for the current tree rubocop: disable CodeReuse/ActiveRecord


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'app/helpers/tree_helper.rb', line 14

def render_tree(tree)
  # Sort submodules and folders together by name ahead of files
  folders, files, submodules = tree.trees, tree.blobs, tree.submodules
  tree = []
  items = (folders + submodules).sort_by(&:name) + files

  if items.size > FILE_LIMIT
    tree << render(partial: 'projects/tree/truncated_notice_tree_row',
                   locals: { limit: FILE_LIMIT, total: items.size })
    items = items.take(FILE_LIMIT)
  end

  tree << render(partial: 'projects/tree/tree_row', collection: items) if items.present?
  tree.join.html_safe
end

#selected_branchObject


162
163
164
# File 'app/helpers/tree_helper.rb', line 162

def selected_branch
  @branch_name || tree_edit_branch
end

#tree_content_data(logs_path, project, path) ⇒ Object

project and path are used on the EE version


171
172
173
174
175
# File 'app/helpers/tree_helper.rb', line 171

def tree_content_data(logs_path, project, path)
  {
    "logs-path" => logs_path
  }
end

#tree_edit_branch(project = @project, ref = @ref) ⇒ Object


72
73
74
75
76
77
78
79
80
# File 'app/helpers/tree_helper.rb', line 72

def tree_edit_branch(project = @project, ref = @ref)
  return unless can_edit_tree?(project, ref)

  if user_access(project).can_push_to_branch?(ref)
    ref
  else
    patch_branch_name(ref)
  end
end

#tree_edit_project(project = @project) ⇒ Object


99
100
101
102
103
104
105
# File 'app/helpers/tree_helper.rb', line 99

def tree_edit_project(project = @project)
  if can?(current_user, :push_code, project)
    project
  elsif current_user && current_user.already_forked?(project)
    current_user.fork_of(project)
  end
end

#tree_icon(type, mode, name) ⇒ Object

Return an image icon depending on the file type and mode

type - String type of the tree item; either 'folder' or 'file' mode - File unix mode name - File name


36
37
38
# File 'app/helpers/tree_helper.rb', line 36

def tree_icon(type, mode, name)
  sprite_icon(file_type_icon_class(type, mode, name))
end

#tree_join(*args) ⇒ Object

Simple shortcut to File.join


55
56
57
# File 'app/helpers/tree_helper.rb', line 55

def tree_join(*args)
  File.join(*args)
end

#up_dir_pathObject


152
153
154
155
# File 'app/helpers/tree_helper.rb', line 152

def up_dir_path
  file = File.join(@path, "..")
  tree_join(@ref, file)
end

#vue_file_list_data(project, ref) ⇒ Object


211
212
213
214
215
216
217
218
219
# File 'app/helpers/tree_helper.rb', line 211

def vue_file_list_data(project, ref)
  {
    project_path: project.full_path,
    project_short_path: project.path,
    ref: ref,
    escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref),
    full_name: project.name_with_namespace
  }
end

#web_ide_button_data(options = {}) ⇒ Object


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'app/helpers/tree_helper.rb', line 221

def web_ide_button_data(options = {})
  {
    project_path: project_to_use.full_path,
    ref: ActionDispatch::Journey::Router::Utils.escape_path(@ref),

    is_fork: fork?,
    needs_to_fork: needs_to_fork?,
    gitpod_enabled: !current_user.nil? && current_user.gitpod_enabled,
    is_blob: !options[:blob].nil?,

    show_edit_button: show_edit_button?,
    show_web_ide_button: show_web_ide_button?,
    show_gitpod_button: show_gitpod_button?,

    web_ide_url: web_ide_url,
    edit_url: edit_url,
    gitpod_url: gitpod_url
  }
end