Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Improve --only/--ignore parameters on Theme pull/push commands to work without quotes #2066

Merged
merged 9 commits into from
Feb 22, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h

### Fixed
* [#2030](https://github.com/Shopify/shopify-cli/pull/2030): Fix Theme::Syncer handling of file deletions in `download_file!`
* [#2066](https://github.com/Shopify/shopify-cli/pull/2066): Improve `--only`/`--ignore` parameters on Theme `pull`/`push` commands to work without quotes

## Version 2.11.2
### Fixed
Expand Down
65 changes: 65 additions & 0 deletions lib/project_types/theme/commands/common/root_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

module Theme
class Command
module Common
module RootHelper
def root_value(options, name)
argv = default_argv(options)
command_index = argv.index(name.to_s)

return "." if command_index.nil?

next_index = command_index + 1
option_by_key = options_map(options)

while next_index < argv.size
element = argv[next_index]
option = option_by_key[element]

return element if option.nil?

# Skip the option argument
next_index += 1 unless option.arg.nil?

# PATTERN arguments take precedence over the `root`
if option.arg =~ /PATTERN/
next_index += 1 while option_argument?(argv, next_index, option_by_key)
next
end

next_index += 1
end

"."
end

private

def default_argv(options)
options.parser.default_argv
end

def options_map(options)
map = {}
options_list(options).each do |option|
map[option.short.first] = option
map[option.long.first] = option
end
map
end

def options_list(options)
options.parser.top.list
end

def option_argument?(argv, next_index, option_by_key)
return false unless next_index < argv.size

element = argv[next_index]
option_by_key[element].nil?
end
end
end
end
end
22 changes: 15 additions & 7 deletions lib/project_types/theme/commands/pull.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,43 @@
require "shopify_cli/theme/ignore_filter"
require "shopify_cli/theme/include_filter"
require "shopify_cli/theme/syncer"
require "project_types/theme/commands/common/root_helper"
require "project_types/theme/conversions/include_glob"
require "project_types/theme/conversions/ignore_glob"

module Theme
class Command
class Pull < ShopifyCLI::Command::SubCommand
include Common::RootHelper

recommend_default_ruby_range

options do |parser, flags|
Conversions::IncludeGlob.register(parser)
Conversions::IgnoreGlob.register(parser)

parser.on("-n", "--nodelete") { flags[:nodelete] = true }
parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
parser.on("-l", "--live") { flags[:live] = true }
parser.on("-d", "--development") { flags[:development] = true }
parser.on("-o", "--only=PATTERN") do |pattern|
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
flags[:includes] ||= []
flags[:includes] << pattern
flags[:includes] += pattern
end
parser.on("-x", "--ignore=PATTERN") do |pattern|
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
flags[:ignores] ||= []
flags[:ignores] << pattern
flags[:ignores] += pattern
end
end

def call(args, _name)
root = args.first || "."
def call(_args, name)
root = root_value(options, name)
delete = !options.flags[:nodelete]
theme = find_theme(root, **options.flags)
return if theme.nil?

include_filter = ShopifyCLI::Theme::IncludeFilter.new(options.flags[:includes])
include_filter = ShopifyCLI::Theme::IncludeFilter.new(root, options.flags[:includes])
ignore_filter = ShopifyCLI::Theme::IgnoreFilter.from_path(root)
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]

Expand Down
22 changes: 15 additions & 7 deletions lib/project_types/theme/commands/push.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@
require "shopify_cli/theme/ignore_filter"
require "shopify_cli/theme/include_filter"
require "shopify_cli/theme/syncer"
require "project_types/theme/commands/common/root_helper"
require "project_types/theme/conversions/include_glob"
require "project_types/theme/conversions/ignore_glob"

module Theme
class Command
class Push < ShopifyCLI::Command::SubCommand
include Common::RootHelper

recommend_default_ruby_range

options do |parser, flags|
Conversions::IncludeGlob.register(parser)
Conversions::IgnoreGlob.register(parser)

parser.on("-n", "--nodelete") { flags[:nodelete] = true }
parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
Expand All @@ -20,18 +28,18 @@ class Push < ShopifyCLI::Command::SubCommand
parser.on("-j", "--json") { flags[:json] = true }
parser.on("-a", "--allow-live") { flags[:allow_live] = true }
parser.on("-p", "--publish") { flags[:publish] = true }
parser.on("-o", "--only=PATTERN") do |pattern|
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
flags[:includes] ||= []
flags[:includes] << pattern
flags[:includes] += pattern
end
parser.on("-x", "--ignore=PATTERN") do |pattern|
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
flags[:ignores] ||= []
flags[:ignores] << pattern
flags[:ignores] += pattern
end
end

def call(args, _name)
root = args.first || "."
def call(_args, name)
root = root_value(options, name)
delete = !options.flags[:nodelete]
theme = find_theme(root, **options.flags)
return if theme.nil?
Expand All @@ -42,7 +50,7 @@ def call(args, _name)
return unless CLI::UI::Prompt.confirm(question)
end

include_filter = ShopifyCLI::Theme::IncludeFilter.new(options.flags[:includes])
include_filter = ShopifyCLI::Theme::IncludeFilter.new(root, options.flags[:includes])
ignore_filter = ShopifyCLI::Theme::IgnoreFilter.from_path(root)
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]

Expand Down
7 changes: 5 additions & 2 deletions lib/project_types/theme/commands/serve.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# frozen_string_literal: true
require "shopify_cli/theme/dev_server"
require "project_types/theme/commands/common/root_helper"

module Theme
class Command
class Serve < ShopifyCLI::Command::SubCommand
include Common::RootHelper

recommend_default_ruby_range

DEFAULT_HTTP_HOST = "127.0.0.1"
Expand All @@ -15,8 +18,8 @@ class Serve < ShopifyCLI::Command::SubCommand
parser.on("--live-reload=MODE") { |mode| flags[:mode] = as_reload_mode(mode) }
end

def call(args, _name)
root = args.first || "."
def call(_args, name)
root = root_value(options, name)
flags = options.flags.dup
host = flags[:host] || DEFAULT_HTTP_HOST
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
Expand Down
50 changes: 50 additions & 0 deletions lib/project_types/theme/conversions/base_glob.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module Theme
module Conversions
class BaseGlob
class << self
def register(parser)
parser.accept(self) { |_val| convert(parser) }
end

def convert(parser)
argv = parser.default_argv
option_index = argv.index { |v| options.include?(v) }

return [] if option_index.nil?

start_index = option_index + 1
option_by_key = options_map(parser)
values = []

argv[start_index..-1].each do |value|
return values unless option_by_key[value].nil?
values << value
end

values
end

def options
raise "`#{self.class.name}#options` must be defined"
end

private

def options_map(parser)
map = {}
parser.top.list.each do |option|
map[option.short.first] = option
map[option.long.first] = option
end
map
end

def parameter?(value)
value.start_with?("-")
end
end
end
end
end
15 changes: 15 additions & 0 deletions lib/project_types/theme/conversions/ignore_glob.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require_relative "base_glob"

module Theme
module Conversions
class IgnoreGlob < BaseGlob
class << self
def options
%w(-x --ignore)
end
end
end
end
end
15 changes: 15 additions & 0 deletions lib/project_types/theme/conversions/include_glob.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require_relative "base_glob"

module Theme
module Conversions
class IncludeGlob < BaseGlob
class << self
def options
%w(-o --only)
end
end
end
end
end
6 changes: 4 additions & 2 deletions lib/shopify_cli/theme/include_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class IncludeFilter

attr_reader :globs, :regexes

def initialize(patterns = [])
def initialize(root, patterns = [])
@root = Pathname.new(root)
@patterns = patterns.nil? ? [] : patterns.compact.reject(&:empty?)

regexes, globs = patterns_to_regexes_and_globs(@patterns)
Expand All @@ -22,9 +23,10 @@ def match?(path)
return true unless present?(@patterns)

path = path.to_s

return true if path.empty?

path = @root.join(path).to_s

regexes.each do |regex|
return true if regex_match?(regex, path)
end
Expand Down
Loading