mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Add basic checkout instructions
This commit adds very basic checkout instructions similar
to `openproject-checkout` to repositories.
Issues:
* Uses table style for checkout component, as exact styling is unclear
* Adds compressed table style with less padding
* Checkout settings are best organized in a Hash with keys per SCM
* vendor. Using default settings, a lot of new setting values would be
introduced
* Checks for Hash in SettingsController
* Currently can't use SettingsHelper, as it requires single setting
values
This commit is contained in:
@@ -36,7 +36,7 @@ See doc/COPYRIGHT.rdoc for more details.
|
||||
|
||||
|
||||
/** Sync SCM vendor select when enabled SCMs are changed */
|
||||
$('[name="settings[enabled_scm][]"]').change(function () {
|
||||
$('[name="settings[enabled_scm][]"]').change(function() {
|
||||
var wasDisabled = !this.checked,
|
||||
vendor = this.value,
|
||||
select = $('#settings_repositories_automatic_managed_vendor'),
|
||||
@@ -51,7 +51,19 @@ See doc/COPYRIGHT.rdoc for more details.
|
||||
if (wasDisabled && option.prop('selected')) {
|
||||
select.val('');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/** Toggle repository checkout fieldsets required when option is disabled */
|
||||
$('.settings-repositories--checkout-toggle').change(function() {
|
||||
var wasChecked = this.checked,
|
||||
fieldset = $(this).closest('fieldset');
|
||||
|
||||
fieldset
|
||||
.find('input,select,textarea')
|
||||
.filter(':not([type=checkbox])')
|
||||
.filter(':not([type=hidden])')
|
||||
.removeAttr('required') // Rails 4.0 still seems to use attribute
|
||||
.prop('required', wasChecked);
|
||||
})
|
||||
});
|
||||
}(jQuery));
|
||||
|
||||
@@ -38,6 +38,25 @@
|
||||
</form>
|
||||
```
|
||||
|
||||
## Forms: Bordered compressed style (less padding)
|
||||
|
||||
```
|
||||
<form class="form -bordered -compressed">
|
||||
<div class="form--field -required">
|
||||
<label class="form--label">Text:</label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--text-field-container">
|
||||
<input type="text" class="form--text-field">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="form--separator">
|
||||
<button class="button -highlight">Save</button>
|
||||
<button class="button">Cancel</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
## Forms: Standard layout
|
||||
|
||||
```
|
||||
|
||||
@@ -58,6 +58,9 @@ $form--field-types: (text-field, text-area, select, check-box, radio-button, ran
|
||||
background-color: $content-form-bg-color
|
||||
border: $content-form-border
|
||||
|
||||
&.-compressed
|
||||
padding: 10px 20px 0 20px
|
||||
|
||||
.form--separator
|
||||
border: 0
|
||||
border-bottom: 1px solid $content-form-separator-color
|
||||
@@ -328,6 +331,9 @@ fieldset.form--fieldset
|
||||
@extend %form--field-after-container
|
||||
font-style: italic
|
||||
|
||||
&.-no-italic
|
||||
font-style: normal
|
||||
|
||||
.form--field-extra-actions
|
||||
@extend %form--field-after-container
|
||||
@include grid-visible-overflow
|
||||
|
||||
@@ -308,6 +308,11 @@ class RepositoriesController < ApplicationController
|
||||
@repository = @project.repository
|
||||
(render_404; return false) unless @repository
|
||||
|
||||
# Prepare checkout instructions
|
||||
# available on all pages (even empty!)
|
||||
@instructions = ::Scm::CheckoutInstructionsService.new(@repository)
|
||||
|
||||
# Asserts repository availability, or renders an appropriate error
|
||||
@repository.scm.check_availability!
|
||||
|
||||
@path = params[:path] || ''
|
||||
|
||||
@@ -48,6 +48,8 @@ class SettingsController < ApplicationController
|
||||
if value.is_a?(Array)
|
||||
# remove blank values in array settings
|
||||
value.delete_if(&:blank?)
|
||||
elsif value.is_a?(Hash)
|
||||
value.delete_if { |_, v| v.blank? }
|
||||
else
|
||||
value = value.strip
|
||||
end
|
||||
|
||||
@@ -129,6 +129,10 @@ class Repository < ActiveRecord::Base
|
||||
false
|
||||
end
|
||||
|
||||
def supports_checkout_info?
|
||||
true
|
||||
end
|
||||
|
||||
def entry(path = nil, identifier = nil)
|
||||
scm.entry(path, identifier)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#-- encoding: UTF-8
|
||||
#-- copyright
|
||||
# OpenProject is a project management system.
|
||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See doc/COPYRIGHT.rdoc for more details.
|
||||
#++
|
||||
|
||||
##
|
||||
# Implements a repository service for building checkout instructions if supported
|
||||
class Scm::CheckoutInstructionsService
|
||||
attr_reader :repository, :user
|
||||
|
||||
def initialize(repository, user = User.current)
|
||||
@repository = repository
|
||||
@user = user
|
||||
end
|
||||
|
||||
##
|
||||
# Retrieve the checkout URL using the repository vendor information
|
||||
# It may additionally set a path parameter, if the repository supports subtree checkout
|
||||
def checkout_url(path = nil)
|
||||
repository.scm.checkout_url(repository, checkout_base_url, path)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the checkout command from SCM adapter
|
||||
# (e.g., `git clone`)
|
||||
def checkout_command
|
||||
repository.scm.checkout_command
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the checkout base URL as defined in settings.
|
||||
def checkout_base_url
|
||||
checkout_settings['base_url']
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the instructions defined in the settings.
|
||||
def instructions
|
||||
checkout_settings['text']
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true when the checkout URL may target a subtree of the repository.
|
||||
def subtree_checkout?
|
||||
repository.scm.subtree_checkout?
|
||||
end
|
||||
|
||||
##
|
||||
# Returns whether the repository supports showing checkout information
|
||||
# and has been configured for it.
|
||||
def available?
|
||||
checkout_enabled? &&
|
||||
repository.supports_checkout_info? &&
|
||||
checkout_base_url.present?
|
||||
end
|
||||
|
||||
def checkout_enabled?
|
||||
checkout_settings['enabled'].to_i > 0
|
||||
end
|
||||
|
||||
##
|
||||
# Determines whether permissions for the given repository
|
||||
# are available.
|
||||
def permission?
|
||||
repository.managed?
|
||||
end
|
||||
|
||||
##
|
||||
# Returns one of the following permission symbols for the given user
|
||||
#
|
||||
# - :readwrite: When user is allowed to read and commit (:commit_access)
|
||||
# - :read: When user is allowed to checkout the repository, but not commit (:browse_repository)
|
||||
# - :none: Otherwise
|
||||
#
|
||||
# Note that this information is only applicable when the repository is managed,
|
||||
# because otherwise OpenProject does not control the repository permissions.
|
||||
# Use +permission?+ to check whether this is the case.
|
||||
#
|
||||
def permission
|
||||
project = repository.project
|
||||
if user.allowed_to?(:commit_access, project)
|
||||
:readwrite
|
||||
elsif user.allowed_to?(:browse_repository, project)
|
||||
:read
|
||||
else
|
||||
:none
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Returns whether the given user may checkout the repository
|
||||
#
|
||||
# Note that this information is only applicable when the repository is managed,
|
||||
# because otherwise OpenProject does not control the repository permissions.
|
||||
# Use +permission?+ to check whether this is the case.
|
||||
def may_checkout?
|
||||
[:readwrite, :read].include?(permission)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns whether the given user may commit to the repository
|
||||
#
|
||||
# Note that this information is only applicable when the repository is managed,
|
||||
# because otherwise OpenProject does not control the repository permissions.
|
||||
# Use +permission?+ to check whether this is the case.
|
||||
def may_commit?
|
||||
permission == :readwrite
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def checkout_settings
|
||||
@settings ||= begin
|
||||
hash = Setting.repository_checkout_data[repository.vendor.to_s]
|
||||
hash.presence || {}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
<% if instructions.present? && instructions.available? %>
|
||||
<form class="form -bordered -compressed">
|
||||
<fieldset class="form--fieldset -collapsible">
|
||||
<legend class="form--fieldset-legend" title="<%= l('repositories.checkout.instructions') %>"
|
||||
onclick="toggleFieldset(this);"><%= l('repositories.checkout.instructions') %></legend>
|
||||
<div class="form--field">
|
||||
<label class="form--label"><%= l('repositories.checkout.url') %></label>
|
||||
<div class="form--field-container">
|
||||
<div class="form--field-affix">
|
||||
<%= instructions.checkout_command %>
|
||||
</div>
|
||||
<div class="form--text-field-container -xwide">
|
||||
<input type="text" class="form--text-field"
|
||||
onclick="this.focus(); this.select()"
|
||||
readonly="readonly" value="<%= instructions.checkout_url %>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field-instructions -no-italic">
|
||||
<%= simple_format instructions.instructions %>
|
||||
<% if instructions.permission? %>
|
||||
<p>
|
||||
<span><%= l('repositories.checkout.access_permission') %></span>
|
||||
<strong><%= l("repositories.checkout.access.#{instructions.permission}") %></strong>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<% end %>
|
||||
@@ -33,6 +33,7 @@ See doc/COPYRIGHT.rdoc for more details.
|
||||
message: l('repositories.errors.empty_repository')) %></p>
|
||||
</div>
|
||||
</div>
|
||||
<%= render partial: 'checkout_instructions', locals: { repository: @repository, instructions: @instructions } %>
|
||||
<%= call_hook(:view_repositories_show_contextual,
|
||||
{ repository: @repository, project: @project }) %>
|
||||
<%= call_hook(:repositories_below_empty_warning,
|
||||
|
||||
@@ -27,6 +27,7 @@ See doc/COPYRIGHT.rdoc for more details.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= render partial: 'checkout_instructions', locals: { repository: @repository, instructions: @instructions } %>
|
||||
<%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %>
|
||||
|
||||
|
||||
|
||||
@@ -87,7 +87,9 @@ See doc/COPYRIGHT.rdoc for more details.
|
||||
<div class="form--field"><%= setting_text_field :repository_log_display_limit, :size => 6 %></div>
|
||||
<div class="form--field"><%= setting_check_box :repository_authentication_caching_enabled %></div>
|
||||
</section>
|
||||
<fieldset class="form--fieldset"><legend class="form--fieldset-legend"><%= l(:text_work_packages_ref_in_commit_messages) %></legend>
|
||||
<%= render partial: 'repositories_checkout' %>
|
||||
<fieldset class="form--fieldset">
|
||||
<legend class="form--fieldset-legend"><%= l(:text_work_packages_ref_in_commit_messages) %></legend>
|
||||
<div class="form--field">
|
||||
<%= setting_text_field :commit_ref_keywords, :size => 30 %>
|
||||
<div class="form--field-instructions"><%= l(:text_comma_separated) %></div>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<fieldset class="form--fieldset">
|
||||
<legend class="form--fieldset-legend"><%= l('repositories.checkout.instructions') %></legend>
|
||||
<% OpenProject::Scm::Manager.registered.each do |vendor, klass| %>
|
||||
<% vendor = vendor.to_s %>
|
||||
<% setting_base = "settings[repository_checkout_data][#{vendor}]" %>
|
||||
<% enabled = Setting.repository_checkout_data[vendor]['enabled'].to_i > 0 %>
|
||||
<fieldset class="form--fieldset -collapsible collapsed">
|
||||
<legend class="form--fieldset-legend" title="<%= klass.vendor_name %>" onclick="toggleFieldset(this);">
|
||||
<a href="javascript:"><%= klass.vendor_name %>
|
||||
<span class="fieldset-toggle-state-label hidden-for-sighted">expanded</span>
|
||||
</a>
|
||||
</legend>
|
||||
<div class="form--field">
|
||||
<% key = "#{setting_base}[enabled]" %>
|
||||
<input type="hidden" name="<%= key %>" value="0" id="<% "#{key}_hidden" %>" />
|
||||
<%= setting_label key, label: :setting_repository_checkout_display %>
|
||||
<%= styled_check_box_tag key, 1, enabled, class: 'settings-repositories--checkout-toggle' %>
|
||||
<div class="form--field-instructions"><%= l('repositories.checkout.enable_instructions_text') %></div>
|
||||
</div>
|
||||
<div class="form--field">
|
||||
<% key = "#{setting_base}[base_url]" %>
|
||||
<%= setting_label key, label: :setting_repository_checkout_base_url %>
|
||||
<%= styled_text_field_tag key, Setting.repository_checkout_data[vendor]['base_url'],
|
||||
type: 'url', required: enabled %>
|
||||
<div class="form--field-instructions"><%= simple_format l('repositories.checkout.base_url_text') %></div>
|
||||
</div>
|
||||
<div class="form--field">
|
||||
<% key = "#{setting_base}[text]" %>
|
||||
<%= setting_label key, label: :setting_repository_checkout_text %>
|
||||
<%= styled_text_area_tag key, Setting.repository_checkout_data[vendor]['text'],
|
||||
required: enabled %>
|
||||
<div class="form--field-instructions"><%= l('repositories.checkout.text_instructions') %></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
+15
-1
@@ -1286,7 +1286,18 @@ en:
|
||||
|
||||
repositories:
|
||||
autofetch_information: "Check this if you want repositories to be updated automatically when accessing the repository module page.\nThis encompasses the retrieval of commits from the repository and refreshing the required disk storage."
|
||||
checkout_instructions: "Checkout instructions"
|
||||
checkout:
|
||||
access:
|
||||
readwrite: 'Read + Write'
|
||||
read: 'Read-only'
|
||||
none: 'No checkout access, you may only view the repository through this application.'
|
||||
access_permission: 'Your permissions on this repository:'
|
||||
url: "Checkout URL"
|
||||
base_url_text: "The base URL to use for generating checkout URLs (e.g., https://myserver.example.org/repos/).\nNote: The base URL is only used for rewriting checkout URLs in managed repositories. Other repositories are not altered"
|
||||
enable_instructions_text: "Displays checkout instructions defined below on all repository-related pages."
|
||||
instructions: "Checkout instructions"
|
||||
text_instructions: "This text is displayed alongside the checkout URL for guidance on how to check out the repository."
|
||||
not_available: "Checkout instructions are not available for this repository"
|
||||
create_managed_delay: "Please note: The repository is managed, it is created asynchronously on the disk and will be available shortly."
|
||||
create_successful: "The repository has been registered."
|
||||
delete_sucessful: "The repository has been deleted."
|
||||
@@ -1413,6 +1424,9 @@ en:
|
||||
setting_repositories_encodings: "Repositories encodings"
|
||||
setting_repository_authentication_caching_enabled: "Enable caching for authentication request of version control software"
|
||||
setting_repository_storage_cache_minutes: "Repository disk size cache"
|
||||
setting_repository_checkout_display: "Show checkout instructions"
|
||||
setting_repository_checkout_base_url: "Checkout base URL"
|
||||
setting_repository_checkout_text: "Checkout instruction text"
|
||||
setting_repository_log_display_limit: "Maximum number of revisions displayed on file log"
|
||||
setting_rest_api_enabled: "Enable REST web service"
|
||||
setting_self_registration: "Self-registration"
|
||||
|
||||
@@ -280,6 +280,19 @@ journal_aggregation_time_minutes:
|
||||
repository_storage_cache_minutes:
|
||||
default: 720
|
||||
format: int
|
||||
repository_checkout_data:
|
||||
serialized: true
|
||||
default:
|
||||
git:
|
||||
enabled: 0
|
||||
text: |-
|
||||
The data contained in this repository can be downloaded to your computer with Git using the checkout information below.
|
||||
Please consult the documentation of Git if you need more information on the checkout procedure and available clients.
|
||||
subversion:
|
||||
enabled: 0
|
||||
text: |-
|
||||
The data contained in this repository can be downloaded to your computer with Subversion using the checkout information below.
|
||||
Please consult the documentation of Subversion if you need more information on the checkout procedure and available clients.
|
||||
api_max_page_size:
|
||||
format: int
|
||||
default: 500
|
||||
|
||||
@@ -33,6 +33,8 @@ module OpenProject
|
||||
module Scm
|
||||
module Adapters
|
||||
class Base
|
||||
include CheckoutInstructions
|
||||
|
||||
attr_accessor :url, :root_url
|
||||
|
||||
def self.vendor
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#-- encoding: UTF-8
|
||||
#-- copyright
|
||||
# OpenProject is a project management system.
|
||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See doc/COPYRIGHT.rdoc for more details.
|
||||
#++
|
||||
|
||||
module OpenProject
|
||||
module Scm
|
||||
module Adapters
|
||||
module CheckoutInstructions
|
||||
##
|
||||
# Returns the checkout URL for the given repository
|
||||
# based on this adapter's knowledge
|
||||
def checkout_url(repository, base_url, path)
|
||||
checkout_url = if local?
|
||||
::URI.join(with_trailing_slash(base_url),
|
||||
repository.repository_identifier)
|
||||
else
|
||||
url
|
||||
end
|
||||
|
||||
if subtree_checkout? && path.present?
|
||||
::URI.join(with_trailing_slash(checkout_url), path)
|
||||
else
|
||||
checkout_url
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Returns whether the SCM vendor supports subtree checkout
|
||||
def subtree_checkout?
|
||||
false
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the checkout command for this vendor
|
||||
def checkout_command
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
# Ensure URL has a trailing slash.
|
||||
# Needed for base URL, because URI.join will otherwise
|
||||
# assume a relative resource.
|
||||
def with_trailing_slash(url)
|
||||
url = url.to_s
|
||||
|
||||
url << '/' unless url.end_with?('/')
|
||||
url
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -43,6 +43,10 @@ module OpenProject
|
||||
@path_encoding = path_encoding.presence || 'UTF-8'
|
||||
end
|
||||
|
||||
def checkout_command
|
||||
'git clone'
|
||||
end
|
||||
|
||||
def client_command
|
||||
@client_command ||= self.class.config[:client_command] || 'git'
|
||||
end
|
||||
|
||||
@@ -80,6 +80,14 @@ module OpenProject
|
||||
@password = password
|
||||
end
|
||||
|
||||
def checkout_command
|
||||
'svn checkout'
|
||||
end
|
||||
|
||||
def subtree_checkout?
|
||||
true
|
||||
end
|
||||
|
||||
##
|
||||
# Checks the status of this repository and throws unless it can be accessed
|
||||
# correctly by the adapter.
|
||||
|
||||
@@ -100,8 +100,6 @@ module OpenProject
|
||||
"file://#{managed_repository_path}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
##
|
||||
# Repository relative path from scm managed root.
|
||||
# Will be overridden by including models to, e.g.,
|
||||
|
||||
Reference in New Issue
Block a user