mirror of
https://code.forgejo.org/actions/checkout.git
synced 2025-08-14 09:20:51 +00:00
Update logic for preserving local changes in the checkout action
This commit is contained in:
parent
f04b821901
commit
ebd82bae91
2 changed files with 190 additions and 6 deletions
94
dist/index.js
vendored
94
dist/index.js
vendored
|
@ -1339,9 +1339,97 @@ function getSource(settings) {
|
|||
core.startGroup('Checking out the ref');
|
||||
if (settings.preserveLocalChanges) {
|
||||
core.info('Attempting to preserve local changes during checkout');
|
||||
// Use --merge to preserve local changes if possible
|
||||
// This will fail if there are merge conflicts, but that's expected behavior
|
||||
yield git.checkout(checkoutInfo.ref, checkoutInfo.startPoint, ['--merge']);
|
||||
// List and store local files before checkout
|
||||
const fs = __nccwpck_require__(7147);
|
||||
const path = __nccwpck_require__(1017);
|
||||
const localFiles = new Map();
|
||||
try {
|
||||
// Get all files in the workspace that aren't in the .git directory
|
||||
const workspacePath = process.cwd();
|
||||
core.info(`Current workspace path: ${workspacePath}`);
|
||||
// List all files in the current directory using fs
|
||||
const listFilesRecursively = (dir) => {
|
||||
let results = [];
|
||||
const list = fs.readdirSync(dir);
|
||||
list.forEach((file) => {
|
||||
const fullPath = path.join(dir, file);
|
||||
const relativePath = path.relative(workspacePath, fullPath);
|
||||
// Skip .git directory
|
||||
if (relativePath.startsWith('.git'))
|
||||
return;
|
||||
const stat = fs.statSync(fullPath);
|
||||
if (stat && stat.isDirectory()) {
|
||||
// Recursively explore subdirectories
|
||||
results = results.concat(listFilesRecursively(fullPath));
|
||||
}
|
||||
else {
|
||||
// Store file content in memory
|
||||
try {
|
||||
const content = fs.readFileSync(fullPath);
|
||||
localFiles.set(relativePath, content);
|
||||
results.push(relativePath);
|
||||
}
|
||||
catch (readErr) {
|
||||
core.warning(`Failed to read file ${relativePath}: ${readErr}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
return results;
|
||||
};
|
||||
const localFilesList = listFilesRecursively(workspacePath);
|
||||
core.info(`Found ${localFilesList.length} local files to preserve:`);
|
||||
localFilesList.forEach(file => core.info(` - ${file}`));
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`Failed to list local files: ${error}`);
|
||||
}
|
||||
// Perform normal checkout
|
||||
yield git.checkout(checkoutInfo.ref, checkoutInfo.startPoint);
|
||||
// Restore local files that were not tracked by git
|
||||
core.info('Restoring local files after checkout');
|
||||
try {
|
||||
let restoredCount = 0;
|
||||
const execOptions = {
|
||||
cwd: process.cwd(),
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
};
|
||||
for (const [filePath, content] of localFiles.entries()) {
|
||||
// Check if file exists in git using a child process instead of git.execGit
|
||||
const { exec } = __nccwpck_require__(1514);
|
||||
let exitCode = 0;
|
||||
const output = {
|
||||
stdout: '',
|
||||
stderr: ''
|
||||
};
|
||||
// Capture output
|
||||
const options = Object.assign(Object.assign({}, execOptions), { listeners: {
|
||||
stdout: (data) => {
|
||||
output.stdout += data.toString();
|
||||
},
|
||||
stderr: (data) => {
|
||||
output.stderr += data.toString();
|
||||
}
|
||||
} });
|
||||
exitCode = yield exec('git', ['ls-files', '--error-unmatch', filePath], options);
|
||||
if (exitCode !== 0) {
|
||||
// File is not tracked by git, safe to restore
|
||||
const fullPath = path.join(process.cwd(), filePath);
|
||||
// Ensure directory exists
|
||||
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||
fs.writeFileSync(fullPath, content);
|
||||
core.info(`Restored local file: ${filePath}`);
|
||||
restoredCount++;
|
||||
}
|
||||
else {
|
||||
core.info(`Skipping ${filePath} as it's tracked by git`);
|
||||
}
|
||||
}
|
||||
core.info(`Successfully restored ${restoredCount} local files`);
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`Failed to restore local files: ${error}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Use the default behavior with --force
|
||||
|
|
|
@ -231,9 +231,105 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
|||
core.startGroup('Checking out the ref')
|
||||
if (settings.preserveLocalChanges) {
|
||||
core.info('Attempting to preserve local changes during checkout')
|
||||
// Use --merge to preserve local changes if possible
|
||||
// This will fail if there are merge conflicts, but that's expected behavior
|
||||
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint, ['--merge'])
|
||||
|
||||
// List and store local files before checkout
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const localFiles = new Map()
|
||||
|
||||
try {
|
||||
// Get all files in the workspace that aren't in the .git directory
|
||||
const workspacePath = process.cwd()
|
||||
core.info(`Current workspace path: ${workspacePath}`)
|
||||
|
||||
// List all files in the current directory using fs
|
||||
const listFilesRecursively = (dir: string): string[] => {
|
||||
let results: string[] = []
|
||||
const list = fs.readdirSync(dir)
|
||||
list.forEach((file: string) => {
|
||||
const fullPath = path.join(dir, file)
|
||||
const relativePath = path.relative(workspacePath, fullPath)
|
||||
// Skip .git directory
|
||||
if (relativePath.startsWith('.git')) return
|
||||
|
||||
const stat = fs.statSync(fullPath)
|
||||
if (stat && stat.isDirectory()) {
|
||||
// Recursively explore subdirectories
|
||||
results = results.concat(listFilesRecursively(fullPath))
|
||||
} else {
|
||||
// Store file content in memory
|
||||
try {
|
||||
const content = fs.readFileSync(fullPath)
|
||||
localFiles.set(relativePath, content)
|
||||
results.push(relativePath)
|
||||
} catch (readErr) {
|
||||
core.warning(`Failed to read file ${relativePath}: ${readErr}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
return results
|
||||
}
|
||||
|
||||
const localFilesList = listFilesRecursively(workspacePath)
|
||||
core.info(`Found ${localFilesList.length} local files to preserve:`)
|
||||
localFilesList.forEach(file => core.info(` - ${file}`))
|
||||
} catch (error) {
|
||||
core.warning(`Failed to list local files: ${error}`)
|
||||
}
|
||||
|
||||
// Perform normal checkout
|
||||
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
|
||||
|
||||
// Restore local files that were not tracked by git
|
||||
core.info('Restoring local files after checkout')
|
||||
try {
|
||||
let restoredCount = 0
|
||||
const execOptions = {
|
||||
cwd: process.cwd(),
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
}
|
||||
|
||||
for (const [filePath, content] of localFiles.entries()) {
|
||||
// Check if file exists in git using a child process instead of git.execGit
|
||||
const { exec } = require('@actions/exec')
|
||||
let exitCode = 0
|
||||
const output = {
|
||||
stdout: '',
|
||||
stderr: ''
|
||||
}
|
||||
|
||||
// Capture output
|
||||
const options = {
|
||||
...execOptions,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output.stdout += data.toString()
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
output.stderr += data.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exitCode = await exec('git', ['ls-files', '--error-unmatch', filePath], options)
|
||||
|
||||
if (exitCode !== 0) {
|
||||
// File is not tracked by git, safe to restore
|
||||
const fullPath = path.join(process.cwd(), filePath)
|
||||
// Ensure directory exists
|
||||
fs.mkdirSync(path.dirname(fullPath), { recursive: true })
|
||||
fs.writeFileSync(fullPath, content)
|
||||
core.info(`Restored local file: ${filePath}`)
|
||||
restoredCount++
|
||||
} else {
|
||||
core.info(`Skipping ${filePath} as it's tracked by git`)
|
||||
}
|
||||
}
|
||||
core.info(`Successfully restored ${restoredCount} local files`)
|
||||
} catch (error) {
|
||||
core.warning(`Failed to restore local files: ${error}`)
|
||||
}
|
||||
} else {
|
||||
// Use the default behavior with --force
|
||||
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue