Implement file preservation system for output directory cleaning
- Add sophisticated file preservation functionality to _clean_output_dir() - Support .qsgen3_preserve file with shell glob patterns for selective preservation - Preserve shared articles and important files during site regeneration - Maintain backward compatibility (no preserve file = complete cleaning) - Add comprehensive documentation in how-it-works.md - Include example preserve file (.qsgen3_preserve.example) - Remove legacy images directory and update documentation - Fix workflow documentation formatting issues
This commit is contained in:
parent
ed7ed0ee18
commit
f72fe18873
40
.qsgen3_preserve.example
Normal file
40
.qsgen3_preserve.example
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# qsgen3 Preserve File
|
||||||
|
#
|
||||||
|
# This file specifies patterns for files that should be preserved during
|
||||||
|
# output directory cleaning. This is useful for keeping shared articles
|
||||||
|
# or other content that should remain accessible even after title changes.
|
||||||
|
#
|
||||||
|
# Format:
|
||||||
|
# - One pattern per line
|
||||||
|
# - Supports shell glob patterns (*, ?, [])
|
||||||
|
# - Lines starting with # are comments
|
||||||
|
# - Empty lines are ignored
|
||||||
|
# - Patterns are relative to the output directory
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
|
||||||
|
# Preserve specific files by exact name
|
||||||
|
# posts/my-important-shared-article.html
|
||||||
|
# about.html
|
||||||
|
|
||||||
|
# Preserve files by pattern
|
||||||
|
# posts/legacy-*.html
|
||||||
|
# *.pdf
|
||||||
|
|
||||||
|
# Preserve entire directories
|
||||||
|
# archive/*
|
||||||
|
# downloads/*
|
||||||
|
|
||||||
|
# Preserve files with specific extensions in certain directories
|
||||||
|
# posts/*.html
|
||||||
|
# docs/*.pdf
|
||||||
|
|
||||||
|
# Example: Preserve a specific shared article
|
||||||
|
# posts/how-to-setup-qsgen3.html
|
||||||
|
|
||||||
|
# Example: Preserve all files in a legacy directory
|
||||||
|
# legacy/*
|
||||||
|
|
||||||
|
# Example: Preserve important documents
|
||||||
|
# important-*.html
|
||||||
|
# *.pdf
|
105
bin/qsgen3
105
bin/qsgen3
@ -599,9 +599,102 @@ _minify_output_directory() {
|
|||||||
# --- Core Functions ---
|
# --- Core Functions ---
|
||||||
_clean_output_dir() {
|
_clean_output_dir() {
|
||||||
_log INFO "Cleaning output directory: ${QSG_CONFIG[paths_output_dir]}"
|
_log INFO "Cleaning output directory: ${QSG_CONFIG[paths_output_dir]}"
|
||||||
# rm -rf "${QSG_CONFIG[paths_output_dir]}"/* # Be careful with this!
|
|
||||||
# For now, just ensure it exists
|
local output_dir="${QSG_CONFIG[paths_output_dir]}"
|
||||||
mkdir -p "${QSG_CONFIG[paths_output_dir]}"
|
local preserve_file="$PROJECT_ROOT/.qsgen3_preserve"
|
||||||
|
|
||||||
|
# If output directory doesn't exist, just create it
|
||||||
|
if [[ ! -d "$output_dir" ]]; then
|
||||||
|
mkdir -p "$output_dir"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
_log DEBUG "Created output directory: $output_dir"
|
||||||
|
else
|
||||||
|
_log ERROR "Failed to create output directory: $output_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if preserve file exists
|
||||||
|
if [[ -f "$preserve_file" ]]; then
|
||||||
|
_log INFO "Found preserve file: $preserve_file"
|
||||||
|
_log DEBUG "Performing selective cleaning with file preservation"
|
||||||
|
|
||||||
|
# Create temporary directory to store preserved files
|
||||||
|
local temp_preserve_dir=$(mktemp -d)
|
||||||
|
local files_preserved=0
|
||||||
|
|
||||||
|
# Read preserve patterns and backup matching files
|
||||||
|
while IFS= read -r pattern || [[ -n "$pattern" ]]; do
|
||||||
|
# Skip empty lines and comments
|
||||||
|
[[ -z "$pattern" || "$pattern" == \#* ]] && continue
|
||||||
|
|
||||||
|
# Remove leading/trailing whitespace
|
||||||
|
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
[[ -z "$pattern" ]] && continue
|
||||||
|
|
||||||
|
_log DEBUG "Processing preserve pattern: $pattern"
|
||||||
|
|
||||||
|
# Find files matching the pattern in output directory
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
# Get relative path from output directory
|
||||||
|
local rel_path="${file#$output_dir/}"
|
||||||
|
local preserve_path="$temp_preserve_dir/$rel_path"
|
||||||
|
|
||||||
|
# Create directory structure in temp location
|
||||||
|
mkdir -p "$(dirname "$preserve_path")"
|
||||||
|
|
||||||
|
# Copy file to preserve location
|
||||||
|
if cp "$file" "$preserve_path"; then
|
||||||
|
files_preserved=$((files_preserved + 1))
|
||||||
|
_log DEBUG "Preserved file: $rel_path"
|
||||||
|
else
|
||||||
|
_log WARNING "Failed to preserve file: $rel_path"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(find "$output_dir" -name "$pattern" -type f -print0 2>/dev/null)
|
||||||
|
|
||||||
|
done < "$preserve_file"
|
||||||
|
|
||||||
|
# Remove the output directory
|
||||||
|
_log DEBUG "Removing output directory contents (preserving $files_preserved files)"
|
||||||
|
rm -rf "$output_dir"
|
||||||
|
|
||||||
|
# Recreate output directory
|
||||||
|
mkdir -p "$output_dir"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
_log ERROR "Failed to recreate output directory: $output_dir"
|
||||||
|
rm -rf "$temp_preserve_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore preserved files
|
||||||
|
if [[ $files_preserved -gt 0 ]]; then
|
||||||
|
_log DEBUG "Restoring $files_preserved preserved files"
|
||||||
|
if [[ -d "$temp_preserve_dir" ]]; then
|
||||||
|
# Copy preserved files back, maintaining directory structure
|
||||||
|
(cd "$temp_preserve_dir" && find . -type f -exec cp --parents {} "$output_dir/" \; 2>/dev/null)
|
||||||
|
_log INFO "Restored $files_preserved preserved files"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up temporary directory
|
||||||
|
rm -rf "$temp_preserve_dir"
|
||||||
|
|
||||||
|
else
|
||||||
|
# No preserve file - do complete cleaning as before
|
||||||
|
_log DEBUG "No preserve file found - performing complete cleaning"
|
||||||
|
rm -rf "$output_dir"
|
||||||
|
mkdir -p "$output_dir"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
_log ERROR "Failed to recreate output directory: $output_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_log DEBUG "Output directory cleaning completed successfully"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
_copy_static_files() {
|
_copy_static_files() {
|
||||||
@ -1168,9 +1261,9 @@ _generate_rss_feed() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local title=$(echo "$frontmatter" | grep -m1 -iE '^title:' | sed -E 's/^title:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/')
|
local title=$(echo "$frontmatter" | grep -m1 -iE '^title:' | sed -E 's/^title:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/')
|
||||||
local date_iso=$(echo "$frontmatter" | grep -m1 -iE '^date:' | sed -E 's/^date:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/')
|
local date_iso=$(echo "$frontmatter" | grep -m1 -iE '^date:' | sed -E 's/^date:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/')
|
||||||
local summary=$(echo "$frontmatter" | grep -m1 -iE '^summary:' | sed -E 's/^summary:[[:space:]]*//i; s/^["\x27](.*)["\x27]$/\1/')
|
local summary=$(echo "$frontmatter" | grep -m1 -iE '^summary:' | sed -E 's/^summary:[[:space:]]*//i; s/^[\"\x27](.*)[\"\x27]$/\1/')
|
||||||
local draft=$(echo "$frontmatter" | grep -m1 -iE '^draft:' | sed -E 's/^draft:[[:space:]]*//i' | tr '[:upper:]' '[:lower:]')
|
local draft=$(echo "$frontmatter" | grep -m1 -iE '^draft:' | sed -E 's/^draft:[[:space:]]*//i' | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
if [[ "$draft" == "true" && "${QSG_CONFIG[build_options_process_drafts]}" != "true" ]]; then
|
if [[ "$draft" == "true" && "${QSG_CONFIG[build_options_process_drafts]}" != "true" ]]; then
|
||||||
|
@ -42,6 +42,7 @@ project-root/
|
|||||||
├── bin/
|
├── bin/
|
||||||
│ └── qsgen3 # Main generator script
|
│ └── qsgen3 # Main generator script
|
||||||
├── site.conf # Main configuration file
|
├── site.conf # Main configuration file
|
||||||
|
├── .qsgen3_preserve # Optional: File preservation patterns
|
||||||
├── content/ # Markdown content
|
├── content/ # Markdown content
|
||||||
│ ├── posts/ # Blog posts
|
│ ├── posts/ # Blog posts
|
||||||
│ │ └── hello-world.md
|
│ │ └── hello-world.md
|
||||||
@ -56,7 +57,6 @@ project-root/
|
|||||||
├── themes/ # Theme directory
|
├── themes/ # Theme directory
|
||||||
│ └── theme-name/ # Individual theme
|
│ └── theme-name/ # Individual theme
|
||||||
│ ├── layouts/ # Theme-specific templates (optional)
|
│ ├── layouts/ # Theme-specific templates (optional)
|
||||||
│ ├── static/ # Theme static assets (optional)
|
|
||||||
│ └── css/ # Alternative theme asset location
|
│ └── css/ # Alternative theme asset location
|
||||||
└── output/ # Generated site (created by qsgen3)
|
└── output/ # Generated site (created by qsgen3)
|
||||||
├── index.html
|
├── index.html
|
||||||
@ -128,8 +128,7 @@ themes/theme-name/
|
|||||||
│ └── rss.xml # RSS template
|
│ └── rss.xml # RSS template
|
||||||
├── static/ # Preferred: Standard static assets location
|
├── static/ # Preferred: Standard static assets location
|
||||||
│ ├── css/
|
│ ├── css/
|
||||||
│ ├── js/
|
│ └── js/
|
||||||
│ └── images/
|
|
||||||
└── css/ # Alternative: Direct CSS location
|
└── css/ # Alternative: Direct CSS location
|
||||||
└── style.css
|
└── style.css
|
||||||
```
|
```
|
||||||
@ -180,10 +179,7 @@ themes/my-theme/
|
|||||||
└── static/ # Static assets
|
└── static/ # Static assets
|
||||||
├── css/
|
├── css/
|
||||||
│ └── style.css # Main stylesheet
|
│ └── style.css # Main stylesheet
|
||||||
├── js/ # JavaScript files (optional)
|
└── js/ # JavaScript files (optional)
|
||||||
│ └── theme.js
|
|
||||||
└── images/ # Theme images (optional)
|
|
||||||
└── logo.png
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option B: CSS-Only Structure**
|
**Option B: CSS-Only Structure**
|
||||||
@ -744,8 +740,7 @@ output/
|
|||||||
│ └── post-name.html
|
│ └── post-name.html
|
||||||
├── static/ # All static assets
|
├── static/ # All static assets
|
||||||
│ ├── css/ # Stylesheets
|
│ ├── css/ # Stylesheets
|
||||||
│ ├── js/ # JavaScript (if provided by theme)
|
│ └── js/ # JavaScript (if provided by theme)
|
||||||
│ └── images/ # Images and media
|
|
||||||
└── css/ # Legacy: Index-specific CSS location
|
└── css/ # Legacy: Index-specific CSS location
|
||||||
└── theme.css # Copy of main theme CSS for index page
|
└── theme.css # Copy of main theme CSS for index page
|
||||||
```
|
```
|
||||||
@ -870,11 +865,52 @@ Process Theme Configuration
|
|||||||
|
|
||||||
```
|
```
|
||||||
Prepare Output Directory
|
Prepare Output Directory
|
||||||
├── Clean existing output directory
|
├── Check for .qsgen3_preserve file in project root
|
||||||
├── Create fresh output directory structure
|
├── If preserve file exists:
|
||||||
└── Prepare for static file copying
|
│ ├── Read file patterns (shell glob patterns)
|
||||||
|
│ ├── Create temporary backup directory
|
||||||
|
│ ├── Find and backup matching files from output directory
|
||||||
|
│ ├── Remove entire output directory
|
||||||
|
│ ├── Recreate clean output directory
|
||||||
|
│ ├── Restore preserved files maintaining directory structure
|
||||||
|
│ └── Clean up temporary backup directory
|
||||||
|
│ └── Remove entire output directory
|
||||||
|
│ └── Create fresh output directory
|
||||||
|
└── Log preservation and cleaning operations
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### File Preservation System
|
||||||
|
|
||||||
|
qsgen3 supports preserving specific files during the cleaning process to handle cases where content has been shared or bookmarked and should remain accessible even after title changes.
|
||||||
|
|
||||||
|
**Preserve File Format (`.qsgen3_preserve`):**
|
||||||
|
- Located in project root directory
|
||||||
|
- One pattern per line using shell glob patterns (`*`, `?`, `[]`)
|
||||||
|
- Lines starting with `#` are comments
|
||||||
|
- Empty lines are ignored
|
||||||
|
- Patterns are relative to the output directory
|
||||||
|
|
||||||
|
**Example preserve patterns:**
|
||||||
|
```bash
|
||||||
|
# Preserve specific shared articles
|
||||||
|
posts/my-important-shared-article.html
|
||||||
|
posts/viral-blog-post.html
|
||||||
|
|
||||||
|
# Preserve files by pattern
|
||||||
|
posts/legacy-*.html
|
||||||
|
archive/*
|
||||||
|
|
||||||
|
# Preserve all PDFs and downloads
|
||||||
|
*.pdf
|
||||||
|
downloads/*
|
||||||
|
```
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Maintains stable URLs for shared content
|
||||||
|
- Prevents broken links when content is renamed
|
||||||
|
- Flexible pattern matching for various preservation needs
|
||||||
|
- Backward compatible (no preserve file = complete cleaning)
|
||||||
|
|
||||||
### 6. Static File Processing
|
### 6. Static File Processing
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -999,6 +1035,31 @@ Complete Generation
|
|||||||
- Verify available disk space
|
- Verify available disk space
|
||||||
- Review path configurations for absolute vs. relative paths
|
- Review path configurations for absolute vs. relative paths
|
||||||
|
|
||||||
|
#### 5. File Preservation Issues
|
||||||
|
**Symptoms**: Expected files not preserved during cleaning, or preservation not working
|
||||||
|
**Causes**:
|
||||||
|
- Incorrect patterns in `.qsgen3_preserve` file
|
||||||
|
- File paths don't match patterns
|
||||||
|
- Permission issues with temporary backup directory
|
||||||
|
- Malformed preserve file format
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
- Verify patterns use shell glob syntax (`*`, `?`, `[]`)
|
||||||
|
- Check that patterns are relative to output directory
|
||||||
|
- Ensure `.qsgen3_preserve` file is in project root
|
||||||
|
- Test patterns with `find output/ -name "pattern"` before adding to preserve file
|
||||||
|
- Enable debug logging to see preservation process details
|
||||||
|
- Verify file permissions allow temporary directory creation
|
||||||
|
|
||||||
|
**Example debugging:**
|
||||||
|
```bash
|
||||||
|
# Test if your pattern matches files
|
||||||
|
find output/ -name "posts/legacy-*.html"
|
||||||
|
|
||||||
|
# Enable debug logging to see preservation process
|
||||||
|
QSG_DEBUG=1 ./bin/qsgen3
|
||||||
|
```
|
||||||
|
|
||||||
### Debug Logging
|
### Debug Logging
|
||||||
|
|
||||||
Enable detailed logging by modifying the `_log` function or adding debug statements:
|
Enable detailed logging by modifying the `_log` function or adding debug statements:
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
Copy this directory to your **www_root**
|
|
||||||
|
|
||||||
**$www_root/images/**
|
|
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" zoomAndPan="magnify" viewBox="0 0 224.87999 225" height="300" preserveAspectRatio="xMidYMid meet" version="1.0"><defs><clipPath id="ec549c68f3"><path d="M 44.976562 24 L 201 24 L 201 179.964844 L 44.976562 179.964844 Z M 44.976562 24 " clip-rule="nonzero"/></clipPath><clipPath id="f9fb9407ba"><path d="M 109 0.0585938 L 224.761719 0.0585938 L 224.761719 116 L 109 116 Z M 109 0.0585938 " clip-rule="nonzero"/></clipPath></defs><g clip-path="url(#ec549c68f3)"><path fill="#000000" d="M 191.742188 84.863281 C 187.179688 84.863281 183.46875 88.574219 183.46875 93.136719 L 183.46875 163.425781 L 61.507812 163.425781 L 61.507812 41.460938 L 131.792969 41.460938 C 136.359375 41.460938 140.070312 37.75 140.070312 33.1875 C 140.070312 28.625 136.359375 24.914062 131.792969 24.914062 L 53.25 24.914062 C 48.6875 24.914062 44.976562 28.625 44.976562 33.1875 L 44.976562 171.679688 C 44.976562 176.242188 48.6875 179.953125 53.25 179.953125 L 191.742188 179.953125 C 196.308594 179.953125 200.019531 176.242188 200.019531 171.679688 L 200.019531 93.136719 C 200.019531 88.574219 196.308594 84.863281 191.742188 84.863281 Z M 191.742188 84.863281 " fill-opacity="1" fill-rule="nonzero"/></g><g clip-path="url(#f9fb9407ba)"><path fill="#000000" d="M 216.585938 0.0703125 L 166.710938 0.0703125 C 162.148438 0.0703125 158.4375 3.78125 158.4375 8.34375 C 158.4375 12.90625 162.128906 16.617188 166.710938 16.617188 L 196.628906 16.617188 L 111.4375 101.789062 C 108.199219 105.027344 108.199219 110.253906 111.4375 113.472656 C 113.046875 115.082031 115.167969 115.898438 117.289062 115.898438 C 119.410156 115.898438 121.53125 115.082031 123.140625 113.472656 L 208.332031 28.28125 L 208.332031 58.21875 C 208.332031 62.78125 212.023438 66.496094 216.605469 66.496094 C 221.167969 66.496094 224.878906 62.78125 224.878906 58.21875 L 224.878906 8.34375 C 224.859375 3.78125 221.148438 0.0703125 216.585938 0.0703125 Z M 216.585938 0.0703125 " fill-opacity="1" fill-rule="nonzero"/></g></svg>
|
|
Before Width: | Height: | Size: 2.0 KiB |
Loading…
x
Reference in New Issue
Block a user