mirror of
https://github.com/tj-actions/changed-files
synced 2025-01-29 13:34:51 +00:00
feat: add support for recovering deleted files (#1269)
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
0621d936c0
commit
77f9e6c7c6
7 changed files with 176 additions and 2 deletions
82
.github/workflows/test.yml
vendored
82
.github/workflows/test.yml
vendored
|
@ -601,6 +601,88 @@ jobs:
|
|||
shell:
|
||||
bash
|
||||
|
||||
test_recover_deleted_file:
|
||||
name: Test changed-files recover deleted file
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
fetch-depth: [0, 1, 2]
|
||||
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
submodules: recursive
|
||||
fetch-depth: ${{ matrix.fetch-depth }}
|
||||
|
||||
- name: Download build assets
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-assets
|
||||
|
||||
- name: Run changed-files with recover_deleted_files
|
||||
id: changed-files-recover-deleted-files
|
||||
uses: ./
|
||||
with:
|
||||
base_sha: "fcdeb5b3d797752d95f6dbe98552a95c29dad338"
|
||||
sha: "432e0c810c60ef1332850a971c5ec39022034b4c"
|
||||
recover_deleted_files: true
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo "${{ toJSON(steps.changed-files-recover-deleted-files.outputs) }}"
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Verify deleted files
|
||||
if: steps.changed-files-recover-deleted-files.outputs.deleted_files != 'test/test deleted.txt'
|
||||
run: |
|
||||
echo "Expected: (test/test deleted.txt) got ${{ steps.changed-files-recover-deleted-files.outputs.deleted_files }}"
|
||||
exit 1
|
||||
|
||||
- name: Verify that test/test deleted.txt is restored
|
||||
run: |
|
||||
if [ ! -f "test/test deleted.txt" ]; then
|
||||
echo "Expected: (test/test deleted.txt) to exist"
|
||||
exit 1
|
||||
else
|
||||
cat "test/test deleted.txt"
|
||||
fi
|
||||
|
||||
- name: Run changed-files with recover_deleted_files and recover_deleted_files_to_destination
|
||||
id: changed-files-recover-deleted-files-to-destination
|
||||
uses: ./
|
||||
with:
|
||||
base_sha: "fcdeb5b3d797752d95f6dbe98552a95c29dad338"
|
||||
sha: "432e0c810c60ef1332850a971c5ec39022034b4c"
|
||||
recover_deleted_files: true
|
||||
recover_deleted_files_to_destination: "deleted_files"
|
||||
|
||||
- name: Show output
|
||||
run: |
|
||||
echo "${{ toJSON(steps.changed-files-recover-deleted-files-to-destination.outputs) }}"
|
||||
shell:
|
||||
bash
|
||||
|
||||
- name: Verify deleted files
|
||||
if: steps.changed-files-recover-deleted-files-to-destination.outputs.deleted_files != 'test/test deleted.txt'
|
||||
run: |
|
||||
echo "Expected: (test/test deleted.txt) got ${{ steps.changed-files-recover-deleted-files-to-destination.outputs.deleted_files }}"
|
||||
exit 1
|
||||
|
||||
- name: Verify that test/test deleted.txt is restored
|
||||
run: |
|
||||
if [ ! -f "deleted_files/test/test deleted.txt" ]; then
|
||||
echo "Expected: (deleted_files/test/test deleted.txt) to exist"
|
||||
exit 1
|
||||
else
|
||||
cat "deleted_files/test/test deleted.txt"
|
||||
fi
|
||||
|
||||
test:
|
||||
name: Test changed-files
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
|
|
@ -145,6 +145,14 @@ inputs:
|
|||
description: "Output renamed files as deleted and added files."
|
||||
required: false
|
||||
default: "false"
|
||||
recover_deleted_files:
|
||||
description: "Recover deleted files."
|
||||
required: false
|
||||
default: "false"
|
||||
recover_deleted_files_to_destination:
|
||||
description: "Recover deleted files to a new destination directory, defaults to the original location."
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
outputs:
|
||||
added_files:
|
||||
|
|
BIN
dist/index.js
generated
vendored
BIN
dist/index.js
generated
vendored
Binary file not shown.
BIN
dist/index.js.map
generated
vendored
BIN
dist/index.js.map
generated
vendored
Binary file not shown.
|
@ -37,6 +37,8 @@ export type Inputs = {
|
|||
writeOutputFiles: boolean
|
||||
outputDir: string
|
||||
outputRenamedFilesAsDeletedAndAdded: boolean
|
||||
recoverDeletedFiles: boolean
|
||||
recoverDeletedFilesToDestination: string
|
||||
}
|
||||
|
||||
export const getInputs = (): Inputs => {
|
||||
|
@ -145,6 +147,13 @@ export const getInputs = (): Inputs => {
|
|||
'output_renamed_files_as_deleted_and_added',
|
||||
{required: false}
|
||||
)
|
||||
const recoverDeletedFiles = core.getBooleanInput('recover_deleted_files', {
|
||||
required: false
|
||||
})
|
||||
const recoverDeletedFilesToDestination = core.getInput(
|
||||
'recover_deleted_files_to_destination',
|
||||
{required: false}
|
||||
)
|
||||
|
||||
const inputs: Inputs = {
|
||||
files,
|
||||
|
@ -180,7 +189,9 @@ export const getInputs = (): Inputs => {
|
|||
sinceLastRemoteCommit,
|
||||
writeOutputFiles,
|
||||
outputDir,
|
||||
outputRenamedFilesAsDeletedAndAdded
|
||||
outputRenamedFilesAsDeletedAndAdded,
|
||||
recoverDeletedFiles,
|
||||
recoverDeletedFilesToDestination
|
||||
}
|
||||
|
||||
if (fetchDepth) {
|
||||
|
|
10
src/main.ts
10
src/main.ts
|
@ -1,6 +1,6 @@
|
|||
import * as core from '@actions/core'
|
||||
import path from 'path'
|
||||
import {getAllDiffFiles, getRenamedFiles} from './changedFiles'
|
||||
import {ChangeTypeEnum, getAllDiffFiles, getRenamedFiles} from './changedFiles'
|
||||
import {setChangedFilesOutput} from './changedFilesOutput'
|
||||
import {
|
||||
DiffResult,
|
||||
|
@ -14,6 +14,7 @@ import {
|
|||
getSubmodulePath,
|
||||
getYamlFilePatterns,
|
||||
isRepoShallow,
|
||||
recoverDeletedFiles,
|
||||
setOutput,
|
||||
submoduleExists,
|
||||
updateGitGlobalConfig,
|
||||
|
@ -118,6 +119,13 @@ export async function run(): Promise<void> {
|
|||
core.info('All Done!')
|
||||
core.endGroup()
|
||||
|
||||
await recoverDeletedFiles({
|
||||
inputs,
|
||||
workingDirectory,
|
||||
deletedFiles: allDiffFiles[ChangeTypeEnum.Deleted],
|
||||
sha: diffResult.previousSha
|
||||
})
|
||||
|
||||
const filePatterns = await getFilePatterns({
|
||||
inputs,
|
||||
workingDirectory
|
||||
|
|
65
src/utils.ts
65
src/utils.ts
|
@ -1032,3 +1032,68 @@ export const setOutput = async ({
|
|||
await fs.writeFile(outputFilePath, cleanedValue.replace(/\\"/g, '"'))
|
||||
}
|
||||
}
|
||||
|
||||
const getDeletedFileContents = async ({
|
||||
cwd,
|
||||
filePath,
|
||||
sha
|
||||
}: {
|
||||
cwd: string
|
||||
filePath: string
|
||||
sha: string
|
||||
}): Promise<string> => {
|
||||
const {stdout, exitCode, stderr} = await exec.getExecOutput(
|
||||
'git',
|
||||
['show', `${sha}:${filePath}`],
|
||||
{
|
||||
cwd,
|
||||
silent: process.env.RUNNER_DEBUG !== '1',
|
||||
ignoreReturnCode: true
|
||||
}
|
||||
)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(
|
||||
`Error getting file content from git history "${filePath}": ${stderr}`
|
||||
)
|
||||
}
|
||||
|
||||
return stdout
|
||||
}
|
||||
|
||||
export const recoverDeletedFiles = async ({
|
||||
inputs,
|
||||
workingDirectory,
|
||||
deletedFiles,
|
||||
sha
|
||||
}: {
|
||||
inputs: Inputs
|
||||
workingDirectory: string
|
||||
deletedFiles: string[]
|
||||
sha: string
|
||||
}): Promise<void> => {
|
||||
if (inputs.recoverDeletedFiles) {
|
||||
for (const deletedFile of deletedFiles) {
|
||||
let target = path.join(workingDirectory, deletedFile)
|
||||
|
||||
if (inputs.recoverDeletedFilesToDestination) {
|
||||
target = path.join(
|
||||
workingDirectory,
|
||||
inputs.recoverDeletedFilesToDestination,
|
||||
deletedFile
|
||||
)
|
||||
}
|
||||
|
||||
const deletedFileContents = await getDeletedFileContents({
|
||||
cwd: workingDirectory,
|
||||
filePath: deletedFile,
|
||||
sha
|
||||
})
|
||||
|
||||
if (!(await exists(path.dirname(target)))) {
|
||||
await fs.mkdir(path.dirname(target), {recursive: true})
|
||||
}
|
||||
await fs.writeFile(target, deletedFileContents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue