FEATURE: option to update child theme components via theme CLI.

FEATURE: option to update child theme components via theme CLI.

https://github.com/discourse/discourse_theme/commit/423ce44112ac1ac56eaafa36252b7d7eea04193f

diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
index d6bc528..00e1799 100644
--- a/app/controllers/admin/themes_controller.rb
+++ b/app/controllers/admin/themes_controller.rb
@@ -97,9 +97,10 @@ class Admin::ThemesController < Admin::AdminController
       # params[:bundle] used by theme CLI. params[:theme] used by admin UI
       bundle = params[:bundle] || params[:theme]
       theme_id = params[:theme_id]
+      update_components = params[:components]
       match_theme_by_name = !!params[:bundle] && !params.key?(:theme_id) # Old theme CLI behavior, match by name. Remove Jan 2020
       begin
-        @theme = RemoteTheme.update_zipped_theme(bundle.path, bundle.original_filename, match_theme: match_theme_by_name, user: theme_user, theme_id: theme_id)
+        @theme = RemoteTheme.update_zipped_theme(bundle.path, bundle.original_filename, match_theme: match_theme_by_name, user: theme_user, theme_id: theme_id, update_components: update_components)
         log_theme_change(nil, @theme)
         render json: @theme, status: :created
       rescue RemoteTheme::ImportError => e
diff --git a/app/models/remote_theme.rb b/app/models/remote_theme.rb
index e95fe25..292ba79 100644
--- a/app/models/remote_theme.rb
+++ b/app/models/remote_theme.rb
@@ -30,17 +30,22 @@ class RemoteTheme < ActiveRecord::Base
     raise ImportError.new I18n.t("themes.import_error.about_json")
   end
 
-  def self.update_zipped_theme(filename, original_filename, match_theme: false, user: Discourse.system_user, theme_id: nil)
+  def self.update_zipped_theme(filename, original_filename, match_theme: false, user: Discourse.system_user, theme_id: nil, update_components: nil)
     importer = ThemeStore::ZipImporter.new(filename, original_filename)
     importer.import!
 
     theme_info = RemoteTheme.extract_theme_info(importer)
     theme = Theme.find_by(name: theme_info["name"]) if match_theme # Old theme CLI method, remove Jan 2020
     theme = Theme.find_by(id: theme_id) if theme_id # New theme CLI method
-    theme ||= Theme.new(user_id: user&.id || -1, name: theme_info["name"])
+
+    existing = true
+    if theme.blank?
+      theme = Theme.new(user_id: user&.id || -1, name: theme_info["name"])
+      existing = false
+    end
 
     theme.component = theme_info["component"].to_s == "true"
-    theme.child_components = theme_info["components"].presence || []
+    theme.child_components = child_components = theme_info["components"].presence || []
 
     remote_theme = new
     remote_theme.theme = theme
@@ -48,6 +53,19 @@ class RemoteTheme < ActiveRecord::Base
     remote_theme.update_from_remote(importer, skip_update: true)
 
     theme.save!
+
+    if existing && update_components.present? && update_components != "none"
+      child_components = child_components.map { |url| ThemeStore::GitImporter.new(url.strip).url }
+
+      if update_components == "sync"
+        ChildTheme.joins(child_theme: :remote_theme).where("remote_themes.remote_url NOT IN (?)", child_components).delete_all
+      end
+
+      child_components -= theme.child_themes.joins(:remote_theme).where("remote_themes.remote_url IN (?)", child_components).pluck("remote_themes.remote_url")
+      theme.child_components = child_components
+      theme.update_child_components
+    end
+
     theme
   ensure
     begin
diff --git a/app/models/theme.rb b/app/models/theme.rb
index c20e04d..69f6c28 100644
--- a/app/models/theme.rb
+++ b/app/models/theme.rb
@@ -25,6 +25,8 @@ class Theme < ActiveRecord::Base
 
   validate :component_validations
 
+  after_create :update_child_components
+
   scope :user_selectable, ->() {
     where('user_selectable OR id = ?', SiteSetting.default_theme_id)
   }
@@ -70,7 +72,7 @@ class Theme < ActiveRecord::Base
     notify_theme_change(with_scheme: notify_with_scheme)
   end
 
-  after_create do
+  def update_child_components
     if !component? && child_components.present?
       child_components.each do |url|
         url = ThemeStore::GitImporter.new(url.strip).url

GitHub sha: 257f59f3