FEATURE: add branch option to remote theme import
* FEATURE: add branch option to remote theme import * FIX: Add missing variable in params * FIX: Add missing param for import_theme method * SPEC: Add test methods for branch support in git import * FIX: Add missing space to scss style * Do not assume default branch as master * Change branch field placeholder * FIX: add missing div start tag
This commit is contained in:
parent
acba7d2a5d
commit
51aba32651
|
@ -44,7 +44,8 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
options.data.append("theme", $("#file-input")[0].files[0]);
|
options.data.append("theme", $("#file-input")[0].files[0]);
|
||||||
} else {
|
} else {
|
||||||
options.data = {
|
options.data = {
|
||||||
remote: this.get("uploadUrl")
|
remote: this.get("uploadUrl"),
|
||||||
|
branch: this.get("branch")
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.get("privateChecked")) {
|
if (this.get("privateChecked")) {
|
||||||
|
|
|
@ -14,14 +14,21 @@
|
||||||
<label class="radio" for="remote">{{i18n 'upload_selector.from_the_web'}}</label>
|
<label class="radio" for="remote">{{i18n 'upload_selector.from_the_web'}}</label>
|
||||||
{{#if remote}}
|
{{#if remote}}
|
||||||
<div class="inputs">
|
<div class="inputs">
|
||||||
|
<div class='repo'>
|
||||||
{{input value=uploadUrl placeholder="https://github.com/discourse/sample_theme"}}
|
{{input value=uploadUrl placeholder="https://github.com/discourse/sample_theme"}}
|
||||||
<span class="description">{{i18n 'admin.customize.theme.import_web_tip'}}</span>
|
<span class="description">{{i18n 'admin.customize.theme.import_web_tip'}}</span>
|
||||||
|
</div>
|
||||||
|
<div class='branch'>
|
||||||
|
{{input value=branch placeholder="beta"}}
|
||||||
|
<span class="description">{{i18n 'admin.customize.theme.remote_branch'}}</span>
|
||||||
|
</div>
|
||||||
|
<div class='check-private'>
|
||||||
|
<label>
|
||||||
|
{{input type="checkbox" checked=privateChecked}}
|
||||||
|
{{i18n 'admin.customize.theme.is_private'}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
{{#if checkPrivate}}
|
{{#if checkPrivate}}
|
||||||
<div class='check-private'>
|
|
||||||
<label>
|
|
||||||
{{input type="checkbox" checked=privateChecked}}
|
|
||||||
{{i18n 'admin.customize.theme.is_private'}}
|
|
||||||
</label>
|
|
||||||
{{#if privateChecked}}
|
{{#if privateChecked}}
|
||||||
{{#if publicKey}}
|
{{#if publicKey}}
|
||||||
<div class='public-key'>
|
<div class='public-key'>
|
||||||
|
@ -30,10 +37,8 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/d-modal-body}}
|
{{/d-modal-body}}
|
||||||
|
|
|
@ -543,6 +543,10 @@
|
||||||
width: 27%;
|
width: 27%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-body .inputs .branch {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.modal-body .inputs .check-private {
|
.modal-body .inputs .check-private {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
label {
|
label {
|
||||||
|
|
|
@ -76,7 +76,8 @@ class Admin::ThemesController < Admin::AdminController
|
||||||
end
|
end
|
||||||
elsif params[:remote]
|
elsif params[:remote]
|
||||||
begin
|
begin
|
||||||
@theme = RemoteTheme.import_theme(params[:remote], current_user, private_key: params[:private_key])
|
branch = params[:branch] ? params[:branch] : nil
|
||||||
|
@theme = RemoteTheme.import_theme(params[:remote], current_user, private_key: params[:private_key], branch: branch)
|
||||||
render json: @theme, status: :created
|
render json: @theme, status: :created
|
||||||
rescue RuntimeError => e
|
rescue RuntimeError => e
|
||||||
Discourse.warn_exception(e, message: "Error importing theme")
|
Discourse.warn_exception(e, message: "Error importing theme")
|
||||||
|
|
|
@ -38,8 +38,8 @@ class RemoteTheme < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.import_theme(url, user = Discourse.system_user, private_key: nil)
|
def self.import_theme(url, user = Discourse.system_user, private_key: nil, branch: nil)
|
||||||
importer = ThemeStore::GitImporter.new(url, private_key: private_key)
|
importer = ThemeStore::GitImporter.new(url, private_key: private_key, branch: branch)
|
||||||
importer.import!
|
importer.import!
|
||||||
|
|
||||||
theme_info = JSON.parse(importer["about.json"])
|
theme_info = JSON.parse(importer["about.json"])
|
||||||
|
@ -50,6 +50,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||||
theme.remote_theme = remote_theme
|
theme.remote_theme = remote_theme
|
||||||
|
|
||||||
remote_theme.private_key = private_key
|
remote_theme.private_key = private_key
|
||||||
|
remote_theme.branch = branch
|
||||||
remote_theme.remote_url = importer.url
|
remote_theme.remote_url = importer.url
|
||||||
remote_theme.update_from_remote(importer)
|
remote_theme.update_from_remote(importer)
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_remote_version
|
def update_remote_version
|
||||||
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key)
|
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key, branch: branch)
|
||||||
begin
|
begin
|
||||||
importer.import!
|
importer.import!
|
||||||
rescue ThemeStore::GitImporter::ImportFailed => err
|
rescue ThemeStore::GitImporter::ImportFailed => err
|
||||||
|
@ -91,7 +92,7 @@ class RemoteTheme < ActiveRecord::Base
|
||||||
|
|
||||||
unless importer
|
unless importer
|
||||||
cleanup = true
|
cleanup = true
|
||||||
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key)
|
importer = ThemeStore::GitImporter.new(remote_url, private_key: private_key, branch: branch)
|
||||||
begin
|
begin
|
||||||
importer.import!
|
importer.import!
|
||||||
rescue ThemeStore::GitImporter::ImportFailed => err
|
rescue ThemeStore::GitImporter::ImportFailed => err
|
||||||
|
@ -235,6 +236,7 @@ end
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# remote_url :string not null
|
# remote_url :string not null
|
||||||
# remote_version :string
|
# remote_version :string
|
||||||
|
# branch :string
|
||||||
# local_version :string
|
# local_version :string
|
||||||
# about_url :string
|
# about_url :string
|
||||||
# license_url :string
|
# license_url :string
|
||||||
|
|
|
@ -3270,6 +3270,7 @@ en:
|
||||||
import_web_tip: "Repository containing theme"
|
import_web_tip: "Repository containing theme"
|
||||||
import_file_tip: ".dcstyle.json file containing theme"
|
import_file_tip: ".dcstyle.json file containing theme"
|
||||||
is_private: "Theme is in a private git repository"
|
is_private: "Theme is in a private git repository"
|
||||||
|
remote_branch: "Branch"
|
||||||
public_key: "Grant the following public key access to the repo:"
|
public_key: "Grant the following public key access to the repo:"
|
||||||
about_theme: "About Theme"
|
about_theme: "About Theme"
|
||||||
license: "License"
|
license: "License"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddBranchToRemoteTheme < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :remote_themes, :branch, :string
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,13 +5,14 @@ class ThemeStore::GitImporter
|
||||||
class ImportFailed < StandardError; end
|
class ImportFailed < StandardError; end
|
||||||
attr_reader :url
|
attr_reader :url
|
||||||
|
|
||||||
def initialize(url, private_key: nil)
|
def initialize(url, private_key: nil, branch: nil)
|
||||||
@url = url
|
@url = url
|
||||||
if @url.start_with?("https://github.com") && !@url.end_with?(".git")
|
if @url.start_with?("https://github.com") && !@url.end_with?(".git")
|
||||||
@url += ".git"
|
@url += ".git"
|
||||||
end
|
end
|
||||||
@temp_folder = "#{Pathname.new(Dir.tmpdir).realpath}/discourse_theme_#{SecureRandom.hex}"
|
@temp_folder = "#{Pathname.new(Dir.tmpdir).realpath}/discourse_theme_#{SecureRandom.hex}"
|
||||||
@private_key = private_key
|
@private_key = private_key
|
||||||
|
@branch = branch
|
||||||
end
|
end
|
||||||
|
|
||||||
def import!
|
def import!
|
||||||
|
@ -67,7 +68,11 @@ class ThemeStore::GitImporter
|
||||||
|
|
||||||
def import_public!
|
def import_public!
|
||||||
begin
|
begin
|
||||||
Discourse::Utils.execute_command("git", "clone", @url, @temp_folder)
|
if @branch.present?
|
||||||
|
Discourse::Utils.execute_command("git", "clone", "--single-branch", "-b", @branch, @url, @temp_folder)
|
||||||
|
else
|
||||||
|
Discourse::Utils.execute_command("git", "clone", @url, @temp_folder)
|
||||||
|
end
|
||||||
rescue => err
|
rescue => err
|
||||||
raise ImportFailed.new(err.message)
|
raise ImportFailed.new(err.message)
|
||||||
end
|
end
|
||||||
|
@ -83,9 +88,12 @@ class ThemeStore::GitImporter
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Discourse::Utils.execute_command({
|
git_ssh_command = { 'GIT_SSH_COMMAND' => "ssh -i #{ssh_folder}/id_rsa -o StrictHostKeyChecking=no" }
|
||||||
'GIT_SSH_COMMAND' => "ssh -i #{ssh_folder}/id_rsa -o StrictHostKeyChecking=no"
|
if @branch.present?
|
||||||
}, "git", "clone", @url, @temp_folder)
|
Discourse::Utils.execute_command(git_ssh_command, "git", "clone", "--single-branch", "-b", @branch, @url, @temp_folder)
|
||||||
|
else
|
||||||
|
Discourse::Utils.execute_command(git_ssh_command, "git", "clone", @url, @temp_folder)
|
||||||
|
end
|
||||||
rescue => err
|
rescue => err
|
||||||
raise ImportFailed.new(err.message)
|
raise ImportFailed.new(err.message)
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
require 'theme_store/git_importer'
|
||||||
|
|
||||||
|
describe ThemeStore::GitImporter do
|
||||||
|
|
||||||
|
context "#import" do
|
||||||
|
|
||||||
|
let(:url) { "https://github.com/example/example.git" }
|
||||||
|
let(:ssh_url) { "git@github.com:example/example.git" }
|
||||||
|
let(:branch) { "dev" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
hex = "xxx"
|
||||||
|
SecureRandom.stubs(:hex).returns(hex)
|
||||||
|
@temp_folder = "#{Pathname.new(Dir.tmpdir).realpath}/discourse_theme_#{hex}"
|
||||||
|
@ssh_folder = "#{Pathname.new(Dir.tmpdir).realpath}/discourse_theme_ssh_#{hex}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should import from http url" do
|
||||||
|
Discourse::Utils.expects(:execute_command).with("git", "clone", url, @temp_folder)
|
||||||
|
|
||||||
|
importer = ThemeStore::GitImporter.new(url)
|
||||||
|
importer.import!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should import from ssh url" do
|
||||||
|
Discourse::Utils.expects(:execute_command).with({
|
||||||
|
'GIT_SSH_COMMAND' => "ssh -i #{@ssh_folder}/id_rsa -o StrictHostKeyChecking=no"
|
||||||
|
}, "git", "clone", ssh_url, @temp_folder)
|
||||||
|
|
||||||
|
importer = ThemeStore::GitImporter.new(ssh_url, private_key: "private_key")
|
||||||
|
importer.import!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should import branch from http url" do
|
||||||
|
Discourse::Utils.expects(:execute_command).with("git", "clone", "--single-branch", "-b", branch, url, @temp_folder)
|
||||||
|
|
||||||
|
importer = ThemeStore::GitImporter.new(url, branch: branch)
|
||||||
|
importer.import!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should import branch from ssh url" do
|
||||||
|
Discourse::Utils.expects(:execute_command).with({
|
||||||
|
'GIT_SSH_COMMAND' => "ssh -i #{@ssh_folder}/id_rsa -o StrictHostKeyChecking=no"
|
||||||
|
}, "git", "clone", "--single-branch", "-b", branch, ssh_url, @temp_folder)
|
||||||
|
|
||||||
|
importer = ThemeStore::GitImporter.new(ssh_url, private_key: "private_key", branch: branch)
|
||||||
|
importer.import!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue