166 lines
4.0 KiB
Markdown
166 lines
4.0 KiB
Markdown
# Batch Operations on Multiple Revisions
|
|
|
|
## Problem
|
|
|
|
When you need to update descriptions for multiple revisions (e.g., replacing line number references with labels), bash syntax and piping can be tricky.
|
|
|
|
## Anti-Pattern
|
|
|
|
```bash
|
|
# ❌ This will fail with syntax errors
|
|
for rev in unxn mktt stnq; do
|
|
jj log -r $rev | sed 's/L123/label/' | jj desc -r $rev --stdin
|
|
done
|
|
|
|
# Issues:
|
|
# 1. Missing -n1 --no-graph -T description (gets full log output)
|
|
# 2. Unquoted variables ($rev) can break with special chars
|
|
# 3. Complex pipes in one-liners are fragile
|
|
```
|
|
|
|
## Pattern 1: Intermediate Files (Recommended)
|
|
|
|
```bash
|
|
# ✅ Robust pattern using temporary files
|
|
for rev in unxn mktt stnq rwyq roww; do
|
|
# Extract description to file
|
|
jj log -r "$rev" -n1 --no-graph -T description > /tmp/desc_${rev}_old.txt
|
|
|
|
# Transform using sed/awk/etc
|
|
sed -f /tmp/replacements.sed /tmp/desc_${rev}_old.txt > /tmp/desc_${rev}_new.txt
|
|
|
|
# Apply back to revision
|
|
jj desc -r "$rev" --stdin < /tmp/desc_${rev}_new.txt
|
|
done
|
|
|
|
echo "✅ All descriptions updated"
|
|
```
|
|
|
|
**Benefits:**
|
|
- Each step is visible and debuggable
|
|
- Can inspect intermediate files if something goes wrong
|
|
- Easy to retry individual revisions
|
|
- Works with complex transformations
|
|
|
|
## Pattern 2: One Command at a Time
|
|
|
|
```bash
|
|
# ✅ Alternative: Sequential approach
|
|
jj log -r unxn -n1 --no-graph -T description | \
|
|
sed 's/L123/@label/' > /tmp/desc_unxn.txt
|
|
jj desc -r unxn --stdin < /tmp/desc_unxn.txt
|
|
|
|
jj log -r mktt -n1 --no-graph -T description | \
|
|
sed 's/L123/@label/' > /tmp/desc_mktt.txt
|
|
jj desc -r mktt --stdin < /tmp/desc_mktt.txt
|
|
|
|
# etc.
|
|
```
|
|
|
|
**Benefits:**
|
|
- Even more explicit
|
|
- Easy to stop/resume
|
|
- Perfect for copy-paste execution
|
|
|
|
## Pattern 3: Using sed Script File
|
|
|
|
```bash
|
|
# Create reusable sed script
|
|
cat > /tmp/replacements.sed << 'EOF'
|
|
s/L596-617/@types-de-cartes/g
|
|
s/L1242-1253/@carte-eglise/g
|
|
s/L659-665/@couts-marche/g
|
|
EOF
|
|
|
|
# Apply to all revisions
|
|
for rev in unxn mktt stnq; do
|
|
jj log -r "$rev" -n1 --no-graph -T description | \
|
|
sed -f /tmp/replacements.sed | \
|
|
jj desc -r "$rev" --stdin
|
|
done
|
|
```
|
|
|
|
**Benefits:**
|
|
- Reusable transformation logic
|
|
- Easy to test sed script independently
|
|
- Cleaner loop body
|
|
|
|
## Common Mistakes
|
|
|
|
### 1. Missing Template Specification
|
|
|
|
```bash
|
|
# ❌ Wrong: gets formatted log output
|
|
jj log -r xyz | sed 's/old/new/'
|
|
|
|
# ✅ Correct: extract just description
|
|
jj log -r xyz -n1 --no-graph -T description | sed 's/old/new/'
|
|
```
|
|
|
|
### 2. Unquoted Variables
|
|
|
|
```bash
|
|
# ❌ Breaks with special characters in rev names
|
|
for rev in a b c; do
|
|
jj log -r $rev # Unquoted
|
|
done
|
|
|
|
# ✅ Always quote
|
|
for rev in a b c; do
|
|
jj log -r "$rev" # Quoted
|
|
done
|
|
```
|
|
|
|
### 3. Fragile One-Liners
|
|
|
|
```bash
|
|
# ❌ Hard to debug, fragile
|
|
for rev in a b c; do jj log -r $rev -n1 --no-graph -T description | sed 's/x/y/' | jj desc -r $rev --stdin; done
|
|
|
|
# ✅ Readable, debuggable
|
|
for rev in a b c; do
|
|
jj log -r "$rev" -n1 --no-graph -T description | \
|
|
sed 's/x/y/' > /tmp/desc_${rev}.txt
|
|
jj desc -r "$rev" --stdin < /tmp/desc_${rev}.txt
|
|
done
|
|
```
|
|
|
|
## Real-World Example
|
|
|
|
Replacing all line number references with Typst labels across 10 revisions:
|
|
|
|
```bash
|
|
# 1. Create sed replacement script
|
|
cat > /tmp/sed_replacements.txt << 'EOF'
|
|
s/5F\.typ L596-617/5F.typ @types-de-cartes/g
|
|
s/5F\.typ L1242-1253/5F.typ @carte-eglise-en-pierre/g
|
|
s/5F\.typ L659-665/5F.typ @couts-marche/g
|
|
# ... etc
|
|
EOF
|
|
|
|
# 2. Process each revision
|
|
for rev in unxn mktt stnq rwyq roww wltq syun zkru mszz ovrv; do
|
|
jj log -r "$rev" -n1 --no-graph -T description | \
|
|
sed -f /tmp/sed_replacements.txt > "/tmp/desc_${rev}_new.txt"
|
|
jj desc -r "$rev" --stdin < "/tmp/desc_${rev}_new.txt"
|
|
done
|
|
|
|
# 3. Verify one result
|
|
jj log -r mktt -n1 --no-graph -T description | head -5
|
|
```
|
|
|
|
## Verification
|
|
|
|
Always verify the results after batch operations:
|
|
|
|
```bash
|
|
# Quick check: first line of each description
|
|
for rev in unxn mktt stnq; do
|
|
echo "=== $rev ==="
|
|
jj log -r "$rev" -n1 --no-graph -T description | head -3
|
|
done
|
|
|
|
# Or use jj log with custom template
|
|
jj log -r 'unxn | mktt | stnq' -T 'change_id.shortest(4) ++ " " ++ description.first_line() ++ "\n"'
|
|
```
|