@revotools/cli 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/revo +129 -48
- package/package.json +1 -1
package/dist/revo
CHANGED
|
@@ -8,7 +8,7 @@ set -euo pipefail
|
|
|
8
8
|
# Exit cleanly on SIGPIPE (e.g., revo clone | grep, revo status | head)
|
|
9
9
|
trap 'exit 0' PIPE
|
|
10
10
|
|
|
11
|
-
REVO_VERSION="0.
|
|
11
|
+
REVO_VERSION="0.4.0"
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
# === lib/ui.sh ===
|
|
@@ -794,8 +794,52 @@ config_init() {
|
|
|
794
794
|
# Write config
|
|
795
795
|
yaml_write "$REVO_CONFIG_FILE"
|
|
796
796
|
|
|
797
|
-
#
|
|
798
|
-
|
|
797
|
+
# Merge revo's required entries into .gitignore without clobbering
|
|
798
|
+
# any existing user entries.
|
|
799
|
+
config_ensure_gitignore "$dir/.gitignore"
|
|
800
|
+
|
|
801
|
+
return 0
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
# Ensure the given .gitignore contains the entries revo needs
|
|
805
|
+
# (`repos/` and `.revo/`). Existing content is preserved; only missing
|
|
806
|
+
# entries are appended. Creates the file if it doesn't exist.
|
|
807
|
+
# Usage: config_ensure_gitignore "/path/to/.gitignore"
|
|
808
|
+
config_ensure_gitignore() {
|
|
809
|
+
local gitignore="$1"
|
|
810
|
+
local needed
|
|
811
|
+
needed=$(printf 'repos/\n.revo/\n')
|
|
812
|
+
|
|
813
|
+
if [[ ! -f "$gitignore" ]]; then
|
|
814
|
+
printf '%s\n' "$needed" > "$gitignore"
|
|
815
|
+
return 0
|
|
816
|
+
fi
|
|
817
|
+
|
|
818
|
+
# Append only the entries that aren't already present (exact line match,
|
|
819
|
+
# ignoring leading/trailing whitespace and comments).
|
|
820
|
+
local entry has_entry needs_newline=0
|
|
821
|
+
# If the file is non-empty and doesn't end in a newline, we need to add
|
|
822
|
+
# one before appending so we don't merge into an existing line.
|
|
823
|
+
if [[ -s "$gitignore" ]] && [[ -n "$(tail -c1 "$gitignore" 2>/dev/null)" ]]; then
|
|
824
|
+
needs_newline=1
|
|
825
|
+
fi
|
|
826
|
+
|
|
827
|
+
local appended=0
|
|
828
|
+
while IFS= read -r entry; do
|
|
829
|
+
[[ -z "$entry" ]] && continue
|
|
830
|
+
has_entry=$(awk -v e="$entry" '
|
|
831
|
+
{ sub(/^[[:space:]]+/, ""); sub(/[[:space:]]+$/, "") }
|
|
832
|
+
$0 == e { found = 1; exit }
|
|
833
|
+
END { exit !found }
|
|
834
|
+
' "$gitignore" && printf 'yes' || printf 'no')
|
|
835
|
+
if [[ "$has_entry" == "no" ]]; then
|
|
836
|
+
if [[ $appended -eq 0 ]] && [[ $needs_newline -eq 1 ]]; then
|
|
837
|
+
printf '\n' >> "$gitignore"
|
|
838
|
+
fi
|
|
839
|
+
printf '%s\n' "$entry" >> "$gitignore"
|
|
840
|
+
appended=1
|
|
841
|
+
fi
|
|
842
|
+
done <<< "$needed"
|
|
799
843
|
|
|
800
844
|
return 0
|
|
801
845
|
}
|
|
@@ -1515,45 +1559,13 @@ _init_scan_existing() {
|
|
|
1515
1559
|
fi
|
|
1516
1560
|
}
|
|
1517
1561
|
|
|
1518
|
-
# Write a Claude-first onboarding CLAUDE.md
|
|
1519
|
-
#
|
|
1562
|
+
# Write a Claude-first onboarding CLAUDE.md if and only if the workspace
|
|
1563
|
+
# root has no CLAUDE.md yet. Existing files are left alone — `revo context`
|
|
1564
|
+
# will append its marker-wrapped auto block once repos are added.
|
|
1520
1565
|
_init_write_claude_md() {
|
|
1521
1566
|
local out="$REVO_WORKSPACE_ROOT/CLAUDE.md"
|
|
1522
1567
|
|
|
1523
|
-
if [[ -f "$out" ]]
|
|
1524
|
-
if grep -q "Workspace Tool: revo" "$out" 2>/dev/null; then
|
|
1525
|
-
return 0
|
|
1526
|
-
fi
|
|
1527
|
-
cat >> "$out" << 'EOF'
|
|
1528
|
-
|
|
1529
|
-
---
|
|
1530
|
-
|
|
1531
|
-
## Workspace Tool: revo
|
|
1532
|
-
|
|
1533
|
-
This workspace uses revo to manage multiple repos.
|
|
1534
|
-
Source: https://github.com/jippylong12/revo
|
|
1535
|
-
|
|
1536
|
-
### Setup commands
|
|
1537
|
-
- `revo add <git-url> --tags <tags> [--depends-on <repo>]` — add a repo to workspace
|
|
1538
|
-
- `revo clone` — clone all configured repos
|
|
1539
|
-
- `revo context` — scan repos and regenerate the workspace context section
|
|
1540
|
-
|
|
1541
|
-
### Daily commands
|
|
1542
|
-
- `revo status` — branch and dirty state across all repos
|
|
1543
|
-
- `revo sync` — pull latest across all repos
|
|
1544
|
-
- `revo feature <name>` — create feature branch across all repos
|
|
1545
|
-
- `revo commit "msg"` — commit all dirty repos with same message
|
|
1546
|
-
- `revo push` — push all repos
|
|
1547
|
-
- `revo pr "title"` — create coordinated PRs via gh CLI
|
|
1548
|
-
- `revo exec "cmd" --tag <tag>` — run command in filtered repos
|
|
1549
|
-
|
|
1550
|
-
### Working in this workspace
|
|
1551
|
-
- Repos live in the repos/ subdirectory (or wherever configured in revo.yaml)
|
|
1552
|
-
- Edit files across repos directly
|
|
1553
|
-
- Check .revo/features/ for active feature briefs
|
|
1554
|
-
- Follow dependency order when making cross-repo changes
|
|
1555
|
-
EOF
|
|
1556
|
-
ui_step_done "Appended revo section to existing CLAUDE.md"
|
|
1568
|
+
if [[ -f "$out" ]]; then
|
|
1557
1569
|
return 0
|
|
1558
1570
|
fi
|
|
1559
1571
|
|
|
@@ -1693,16 +1705,18 @@ cmd_init() {
|
|
|
1693
1705
|
fi
|
|
1694
1706
|
fi
|
|
1695
1707
|
|
|
1696
|
-
#
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
#
|
|
1708
|
+
# If we detected repos, hand off to cmd_context — it now wraps its output
|
|
1709
|
+
# in BEGIN/END markers and preserves any user content in CLAUDE.md, so we
|
|
1710
|
+
# don't need the onboarding placeholder. When no repos were detected,
|
|
1711
|
+
# write the placeholder so Claude has something to read.
|
|
1700
1712
|
if [[ $detected_count -gt 0 ]]; then
|
|
1701
1713
|
ui_bar_line
|
|
1702
1714
|
cmd_context
|
|
1703
1715
|
return 0
|
|
1704
1716
|
fi
|
|
1705
1717
|
|
|
1718
|
+
_init_write_claude_md
|
|
1719
|
+
|
|
1706
1720
|
ui_outro "Workspace initialized! Run 'revo add <url>' to add repositories."
|
|
1707
1721
|
return 0
|
|
1708
1722
|
}
|
|
@@ -2752,15 +2766,75 @@ _context_topo_sort() {
|
|
|
2752
2766
|
return 0
|
|
2753
2767
|
}
|
|
2754
2768
|
|
|
2755
|
-
#
|
|
2769
|
+
# Markers used to delimit revo's auto-generated block inside the workspace
|
|
2770
|
+
# CLAUDE.md. Anything between these markers is owned by `revo context` and
|
|
2771
|
+
# replaced on every regeneration. Anything outside is preserved untouched.
|
|
2772
|
+
CONTEXT_BEGIN_MARKER='<!-- BEGIN revo:auto - regenerated by `revo context`, do not edit between markers -->'
|
|
2773
|
+
CONTEXT_END_MARKER='<!-- END revo:auto -->'
|
|
2774
|
+
|
|
2775
|
+
# Splice an auto-generated block into the target CLAUDE.md without
|
|
2776
|
+
# clobbering user content.
|
|
2777
|
+
# - If target doesn't exist: copy auto file to target.
|
|
2778
|
+
# - If target has BEGIN+END markers: replace the marker block in place.
|
|
2779
|
+
# - Otherwise: append the auto block (with a separator) at the end.
|
|
2780
|
+
# Usage: _context_merge_into "/tmp/auto" "/path/to/CLAUDE.md"
|
|
2781
|
+
_context_merge_into() {
|
|
2782
|
+
local auto_file="$1"
|
|
2783
|
+
local target="$2"
|
|
2784
|
+
|
|
2785
|
+
if [[ ! -f "$target" ]]; then
|
|
2786
|
+
cp "$auto_file" "$target"
|
|
2787
|
+
return 0
|
|
2788
|
+
fi
|
|
2789
|
+
|
|
2790
|
+
if grep -qF "$CONTEXT_BEGIN_MARKER" "$target" 2>/dev/null \
|
|
2791
|
+
&& grep -qF "$CONTEXT_END_MARKER" "$target" 2>/dev/null; then
|
|
2792
|
+
local merged
|
|
2793
|
+
merged=$(mktemp -t revo-merge.XXXXXX)
|
|
2794
|
+
awk -v auto="$auto_file" -v begin="$CONTEXT_BEGIN_MARKER" -v end="$CONTEXT_END_MARKER" '
|
|
2795
|
+
BEGIN { in_block = 0 }
|
|
2796
|
+
index($0, begin) == 1 {
|
|
2797
|
+
in_block = 1
|
|
2798
|
+
while ((getline line < auto) > 0) print line
|
|
2799
|
+
close(auto)
|
|
2800
|
+
next
|
|
2801
|
+
}
|
|
2802
|
+
index($0, end) == 1 && in_block {
|
|
2803
|
+
in_block = 0
|
|
2804
|
+
next
|
|
2805
|
+
}
|
|
2806
|
+
!in_block { print }
|
|
2807
|
+
' "$target" > "$merged"
|
|
2808
|
+
mv "$merged" "$target"
|
|
2809
|
+
return 0
|
|
2810
|
+
fi
|
|
2811
|
+
|
|
2812
|
+
# No markers — append at the end with a blank-line separator. If the
|
|
2813
|
+
# existing file doesn't end in a newline, add one first so we don't merge
|
|
2814
|
+
# into the user's last line.
|
|
2815
|
+
if [[ -s "$target" ]] && [[ -n "$(tail -c1 "$target" 2>/dev/null)" ]]; then
|
|
2816
|
+
printf '\n' >> "$target"
|
|
2817
|
+
fi
|
|
2818
|
+
printf '\n' >> "$target"
|
|
2819
|
+
cat "$auto_file" >> "$target"
|
|
2820
|
+
return 0
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
# Write the workspace CLAUDE.md to the given path. The auto-generated content
|
|
2824
|
+
# is wrapped in BEGIN/END markers and spliced into any existing CLAUDE.md so
|
|
2825
|
+
# user content above and below the markers is preserved across regenerations.
|
|
2756
2826
|
# Usage: _context_write_file "/path/to/CLAUDE.md"
|
|
2757
2827
|
_context_write_file() {
|
|
2758
|
-
local
|
|
2828
|
+
local target="$1"
|
|
2759
2829
|
local workspace
|
|
2760
2830
|
workspace=$(config_workspace_name)
|
|
2761
2831
|
|
|
2762
|
-
|
|
2832
|
+
local output
|
|
2833
|
+
output=$(mktemp -t revo-auto.XXXXXX)
|
|
2834
|
+
|
|
2835
|
+
# Start auto block (markers + header)
|
|
2763
2836
|
{
|
|
2837
|
+
printf '%s\n' "$CONTEXT_BEGIN_MARKER"
|
|
2764
2838
|
printf '# Workspace Context (auto-generated by revo)\n'
|
|
2765
2839
|
printf '\n'
|
|
2766
2840
|
printf 'This workspace contains multiple repositories managed by revo.\n'
|
|
@@ -2768,8 +2842,9 @@ _context_write_file() {
|
|
|
2768
2842
|
printf 'Workspace: **%s**\n' "$workspace"
|
|
2769
2843
|
fi
|
|
2770
2844
|
printf '\n'
|
|
2771
|
-
printf '> This
|
|
2772
|
-
printf '>
|
|
2845
|
+
printf '> This block is auto-generated by `revo context`. Edits between the\n'
|
|
2846
|
+
printf '> BEGIN/END markers will be lost on regeneration. Add your own content\n'
|
|
2847
|
+
printf '> above or below the markers.\n'
|
|
2773
2848
|
printf '\n'
|
|
2774
2849
|
printf '## Repos\n'
|
|
2775
2850
|
printf '\n'
|
|
@@ -2946,7 +3021,13 @@ _context_write_file() {
|
|
|
2946
3021
|
printf 'revo commit "feat: my feature" # commits all dirty repos\n'
|
|
2947
3022
|
printf 'revo pr "My feature" # coordinated PRs\n'
|
|
2948
3023
|
printf '```\n'
|
|
3024
|
+
printf '\n'
|
|
3025
|
+
printf '%s\n' "$CONTEXT_END_MARKER"
|
|
2949
3026
|
} >> "$output"
|
|
3027
|
+
|
|
3028
|
+
# Splice the auto block into the target file, preserving any user content.
|
|
3029
|
+
_context_merge_into "$output" "$target"
|
|
3030
|
+
rm -f "$output"
|
|
2950
3031
|
}
|
|
2951
3032
|
|
|
2952
3033
|
cmd_context() {
|