Skip to content

Commit

Permalink
Modify glob pattern subdirectory warning to only render once per exec…
Browse files Browse the repository at this point in the history
…ution
  • Loading branch information
jamesmengo committed Apr 9, 2024
1 parent 72a46ba commit 8ca5366
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
28 changes: 16 additions & 12 deletions packages/theme/src/cli/utilities/asset-ignore.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {applyIgnoreFilters} from './asset-ignore.js'
import {ReadOptions, fileExists, matchGlob, readFile} from '@shopify/cli-kit/node/fs'
import {ReadOptions, fileExists, readFile} from '@shopify/cli-kit/node/fs'
import {outputWarn} from '@shopify/cli-kit/node/output'
import {joinPath} from '@shopify/cli-kit/node/path'
import {test, describe, beforeEach, vi, expect} from 'vitest'
Expand Down Expand Up @@ -132,30 +132,34 @@ describe('applyIgnoreFilters', () => {
])
})

test(`does not output warnings when there are no glob pattern modifications required for subdirectories`, async () => {
test(`only outputs glob pattern subdirectory warnings for the templates folder`, async () => {
// Given
const options = {only: ['templates/*.json']}

const filteredChecksums = checksums.filter(({key}) => !matchGlob(key, 'templates/**/*.json'))

const options = {only: ['assets/*.json', 'config/*.json', 'sections/*.json']}
// When
await applyIgnoreFilters(filteredChecksums, themeFileSystem, options)

await applyIgnoreFilters(checksums, themeFileSystem, options)
// Then
expect(vi.mocked(outputWarn)).not.toHaveBeenCalled()
})

test(`outputs warnings when there are glob pattern modifications required for subdirectories`, async () => {
// Given
const options = {only: ['templates/*.json']}
const numFilesInSubDirectory = checksums.filter(
({key}) => matchGlob(key, 'templates/**/*.json') && !matchGlob(key, 'templates/*.json'),
).length

// When
await applyIgnoreFilters(checksums, themeFileSystem, options)

// Then
expect(vi.mocked(outputWarn)).toHaveBeenCalledTimes(numFilesInSubDirectory)
expect(vi.mocked(outputWarn)).toHaveBeenCalledTimes(1)
})

test('only outputs a single warning for duplicated glob patterns', async () => {
// Given
const options = {only: ['templates/*.json'], ignore: ['templates/*.json']}

// When
await applyIgnoreFilters(checksums, themeFileSystem, options)

// Then
expect(vi.mocked(outputWarn)).toHaveBeenCalledTimes(1)
})
})
36 changes: 25 additions & 11 deletions packages/theme/src/cli/utilities/asset-ignore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ export async function applyIgnoreFilters(
) {
const shopifyIgnore = await shopifyIgnoredPatterns(themeFileSystem)

const ignoreOptions = options.ignore ?? []
const onlyOptions = options.only ?? []

checkPatterns([...shopifyIgnore, ...ignoreOptions, ...onlyOptions])

return themeChecksums
.filter(filterBy(shopifyIgnore, '.shopifyignore'))
.filter(filterBy(options.ignore, '--ignore'))
.filter(filterBy(options.only, '--only', true))
.filter(filterBy(ignoreOptions, '--ignore'))
.filter(filterBy(onlyOptions, '--only', true))
}

function filterBy(patterns: string[] | undefined, type: string, invertMatch = false) {
function filterBy(patterns: string[], type: string, invertMatch = false) {
return ({key}: Checksum) => {
if (!patterns) return true
if (patterns.length === 0) return true

const match = patterns.some((pattern) => matchGlob(key, pattern) || regexMatch(key, pattern))
const shouldIgnore = invertMatch ? !match : match
Expand Down Expand Up @@ -56,20 +61,29 @@ function matchGlob(key: string, pattern: string) {
// When the the standard match fails and the pattern includes '/*.', we
// replace '/*.' with '/**/*.' to emulate Shopify CLI 2.x behavior, as it was
// based on 'File.fnmatch'.
if (pattern.includes('/*.') && !pattern.includes('/**/*.')) {
const newPatternMatch = originalMatchGlob(key, pattern.replace('/*.', '/**/*.'))
if (newPatternMatch) {
if (shouldReplaceGlobPattern(pattern)) {
return originalMatchGlob(key, pattern.replace('/*.', '/**/*.'))
}

return false
}

function checkPatterns(patterns: string[]) {
const allPatterns = new Set(patterns)
allPatterns.forEach((pattern) => {
if (shouldReplaceGlobPattern(pattern)) {
outputWarn(
`Warning: File ${key} does not match the pattern '${pattern}'. To maintain backwards compatibility, we have modified your pattern to ${pattern.replace(
`Warning: The pattern '${pattern}' does not include subdirectories. To maintain backwards compatibility, we have modified your pattern to ${pattern.replace(
'/*.',
'/**/*.',
)} to explicitly include subdirectories.`,
)
}
return newPatternMatch
}
})
}

return false
function shouldReplaceGlobPattern(pattern: string): boolean {
return pattern.includes('/*.') && !pattern.includes('/**/*.') && pattern.includes('templates/')
}

function regexMatch(key: string, pattern: string) {
Expand Down

0 comments on commit 8ca5366

Please sign in to comment.