Skip to content

Commit

Permalink
fix: apply ignore settings when copying file (#745)
Browse files Browse the repository at this point in the history
Co-authored-by: Mark Mindenhall <1106269+mmindenhall@users.noreply.github.com>
  • Loading branch information
scolladon and mmindenhall committed Jan 3, 2024
1 parent d5974f2 commit d6f99d3
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 39 deletions.
107 changes: 81 additions & 26 deletions __tests__/unit/lib/utils/fsHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
scanExtension,
writeFile,
} from '../../../../src/utils/fsHelper'
import {
IgnoreHelper,
buildIgnoreHelper,
} from '../../../../src/utils/ignoreHelper'
import {
getSpawnContent,
treatPathSep,
Expand All @@ -28,6 +32,7 @@ import {
import { EOL } from 'os'
import { Work } from '../../../../src/types/work'
import { Config } from '../../../../src/types/config'
import { Ignore } from 'ignore'

jest.mock('fs-extra')
jest.mock('../../../../src/utils/gitLfsHelper')
Expand All @@ -42,7 +47,9 @@ jest.mock('../../../../src/utils/childProcessUtils', () => {
treatPathSep: jest.fn(),
}
})
jest.mock('../../../../src/utils/ignoreHelper')

const mockBuildIgnoreHelper = jest.mocked(buildIgnoreHelper)
const mockedGetStreamContent = jest.mocked(getSpawnContent)
const mockedTreatPathSep = jest.mocked(treatPathSep)
const mockedStat = jest.mocked(stat)
Expand All @@ -54,7 +61,7 @@ beforeEach(() => {
jest.resetAllMocks()
work = getWork()
work.config.from = 'pastsha'
work.config.from = 'recentsha'
work.config.to = 'recentsha'
})

describe('gitPathSeparatorNormalizer', () => {
Expand Down Expand Up @@ -135,6 +142,13 @@ describe('readPathFromGit', () => {
})

describe('copyFile', () => {
beforeEach(() => {
mockBuildIgnoreHelper.mockResolvedValue({
globalIgnore: {
ignores: () => false,
} as unknown as Ignore,
} as unknown as IgnoreHelper)
})
describe('when file is already copied', () => {
it('should not copy file', async () => {
await copyFiles(work.config, 'source/file')
Expand Down Expand Up @@ -165,25 +179,61 @@ describe('copyFile', () => {
})
})

describe('when source location is empty', () => {
it('should copy file', async () => {
describe('when content is not a git location', () => {
it('should ignore this path', async () => {
// Arrange
mockedTreatPathSep.mockReturnValueOnce('source/copyFile')
mockedGetStreamContent.mockResolvedValue(Buffer.from(''))
const sourcePath = 'source/warning'
mockedGetStreamContent.mockRejectedValue(
`fatal: path '${sourcePath}' does not exist in 'HEAD'`
)

// Act
await copyFiles(work.config, 'source/doNotCopy')
await copyFiles(work.config, sourcePath)

// Assert
expect(getSpawnContent).toBeCalled()
expect(outputFile).toBeCalledWith(
'output/source/copyFile',
Buffer.from('')
)
expect(outputFile).not.toBeCalled()
})
})

describe('when source location is not empty', () => {
describe('when path is ignored', () => {
it('should not copy this path', async () => {
// Arrange
mockBuildIgnoreHelper.mockResolvedValue({
globalIgnore: {
ignores: () => true,
} as unknown as Ignore,
} as unknown as IgnoreHelper)

// Act
await copyFiles(work.config, 'source/ignored')

// Assert
expect(getSpawnContent).not.toBeCalled()
expect(outputFile).not.toBeCalled()
})
})

describe('when content should be copied', () => {
describe('when source location is empty', () => {
it('should copy file', async () => {
// Arrange

mockedTreatPathSep.mockReturnValueOnce('source/copyFile')
mockedGetStreamContent.mockResolvedValue(Buffer.from(''))

// Act
await copyFiles(work.config, 'source/doNotCopy')

// Assert
expect(getSpawnContent).toBeCalled()
expect(outputFile).toBeCalledWith(
'output/source/copyFile',
Buffer.from('')
)
})
})

describe('when content is a folder', () => {
it('should copy the folder', async () => {
// Arrange
Expand All @@ -206,22 +256,7 @@ describe('copyFile', () => {
expect(treatPathSep).toBeCalledTimes(1)
})
})
describe('when content is not a git location', () => {
it('should ignore this path', async () => {
// Arrange
const sourcePath = 'source/warning'
mockedGetStreamContent.mockRejectedValue(
`fatal: path '${sourcePath}' does not exist in 'HEAD'`
)

// Act
await copyFiles(work.config, sourcePath)

// Assert
expect(getSpawnContent).toBeCalled()
expect(outputFile).not.toBeCalled()
})
})
describe('when content is a file', () => {
beforeEach(async () => {
// Arrange
Expand Down Expand Up @@ -549,6 +584,11 @@ describe('pathExists', () => {
describe('writeFile', () => {
beforeEach(() => {
mockedTreatPathSep.mockReturnValue('folder/file')
mockBuildIgnoreHelper.mockResolvedValue({
globalIgnore: {
ignores: () => false,
} as unknown as Ignore,
} as unknown as IgnoreHelper)
})

it.each(['folder/file', 'folder\\file'])(
Expand Down Expand Up @@ -581,6 +621,21 @@ describe('writeFile', () => {
// Assert
expect(outputFile).toBeCalledTimes(1)
})

it('should not copy ignored path', async () => {
// Arrange
mockBuildIgnoreHelper.mockResolvedValue({
globalIgnore: {
ignores: () => true,
} as unknown as Ignore,
} as unknown as IgnoreHelper)

// Act
await writeFile('', '', {} as Config)

// Assert
expect(outputFile).not.toBeCalled()
})
})

describe('dirExists', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/post-processor/flowTranslationProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default class FlowTranslationProcessor extends BaseProcessor {

for (const translationPath of translationsIterator) {
if (
!ignoreHelper?.globalIgnore?.ignores(translationPath) &&
!ignoreHelper.globalIgnore.ignores(translationPath) &&
!isSubDir(this.config.output, translationPath)
) {
await this._parseTranslationFile(translationPath)
Expand Down
25 changes: 19 additions & 6 deletions src/utils/fsHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'
import { readFile as fsReadFile } from 'fs-extra'
import { isAbsolute, join, relative } from 'path'
import { outputFile, stat } from 'fs-extra'
import { readFile as fsReadFile, outputFile, stat } from 'fs-extra'
import {
GIT_COMMAND,
GIT_FOLDER,
Expand All @@ -10,6 +9,7 @@ import {
} from './gitConstants'
import { EOLRegex, getSpawnContent, treatPathSep } from './childProcessUtils'
import { isLFS, getLFSObjectContentPath } from './gitLfsHelper'
import { buildIgnoreHelper } from './ignoreHelper'
import { Config } from '../types/config'

const FOLDER = 'tree'
Expand All @@ -21,9 +21,15 @@ const copiedFiles = new Set()
const writtenFiles = new Set()

export const copyFiles = async (config: Config, src: string) => {
if (copiedFiles.has(src) || writtenFiles.has(src)) return
if (copiedFiles.has(src) || writtenFiles.has(src)) {
return
}
copiedFiles.add(src)

const ignoreHelper = await buildIgnoreHelper(config)
if (ignoreHelper.globalIgnore.ignores(src)) {
return
}
try {
const bufferData: Buffer = await readPathFromGitAsBuffer(src, config)
const utf8Data = bufferData?.toString(UTF8_ENCODING) ?? ''
Expand Down Expand Up @@ -119,11 +125,18 @@ export async function* scan(
export const writeFile = async (
path: string,
content: string,
{ output }: Config
config: Config
) => {
if (writtenFiles.has(path)) return
if (writtenFiles.has(path)) {
return
}
writtenFiles.add(path)
await outputFile(join(output, treatPathSep(path)), content)

const ignoreHelper = await buildIgnoreHelper(config)
if (ignoreHelper.globalIgnore.ignores(path)) {
return
}
await outputFile(join(config.output, treatPathSep(path)), content)
}

export const isSubDir = (parent: string, dir: string) => {
Expand Down
8 changes: 2 additions & 6 deletions src/utils/ignoreHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class IgnoreHelper {
protected readonly destructiveIgnore: Ignore
) {}

public keep(line: string) {
public keep(line: string): boolean {
const changeType = line.charAt(0)

let ignInstance!: Ignore
Expand Down Expand Up @@ -47,7 +47,7 @@ export const buildIgnoreHelper = async ({
? await _buildIgnore(ignoreDestructive)
: await _buildIgnore(ignore)

await _addDefaultDestructiveIgnore(destructiveIgnore)
destructiveIgnore.add(BASE_DESTRUCTIVE_IGNORE)

ignoreInstance = new IgnoreHelper(globalIgnore, destructiveIgnore)
}
Expand Down Expand Up @@ -80,10 +80,6 @@ const _buildIgnore = async (ignorePath: string) => {
return ign
}

const _addDefaultDestructiveIgnore = async (destructiveIgnore: Ignore) => {
destructiveIgnore.add(BASE_DESTRUCTIVE_IGNORE)
}

export const resetIgnoreInstance = () => {
ignoreInstance = null
}
Expand Down

0 comments on commit d6f99d3

Please sign in to comment.