Add cross-machine sync tooling (clone/pull/push all module repos)

repos.txt + sync-*.sh let any machine (Mac or Windows/Git Bash) hydrate all 49
module repos and keep them in sync via GitHub+gitea. Pulls are fast-forward only
(never clobber local work); pushes send commits only and flag uncommitted repos.
See SYNC.md for the two-machine workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-06-09 21:34:32 -04:00
parent 14cd6a666b
commit 4830613701
6 changed files with 241 additions and 0 deletions

58
SYNC.md Normal file
View File

@@ -0,0 +1,58 @@
# Syncing Odoo-Modules across machines (Mac + Windows)
Each module/suite folder here is its **own git repo** (private on GitHub at
`gsinghpal/<name>`, mirrored to gitea `admin/<name>`). This parent folder is a
separate repo that holds the shared files (CLAUDE.md, docs, scripts, these sync
helpers). The cloud (GitHub) is the hub: both machines push to it and pull from it.
Nothing here ever deletes your work. Pulls are fast-forward only, so local changes
are never overwritten; pushes only send commits.
## First-time setup on a new machine (e.g. the Windows PC)
1. Install **Git** (Git for Windows includes "Git Bash", which runs these scripts).
2. Sign in to GitHub once so git can push/pull:
- easiest: `gh auth login` (or let Git Credential Manager prompt on first pull)
3. Get everything:
```
git clone https://github.com/gsinghpal/Odoo-Modules.git
cd Odoo-Modules
bash sync-clone-all.sh
```
That clones the parent, then all 49 module repos into place.
(gitea is an optional second mirror. The first push to it will ask for your
`git.nexasystems.ca` login. If you only use GitHub, those gitea lines just fail
quietly and GitHub stays the source of truth.)
## Daily workflow (same on Mac and Windows)
- **Before you start:** `bash sync-pull-all.sh` - pulls the latest for the parent
and every module. Anything with local changes or a diverged history is skipped and
listed, so you can handle it yourself.
- **Do your work**, then **commit inside the module(s) you changed**:
```
cd fusion_clock
git add -A
git commit -m "..."
cd ..
```
- **When done:** `bash sync-push-all.sh` - pushes every committed change to GitHub
+ gitea, and flags any repo that still has uncommitted changes (so nothing is
silently left behind).
## Golden rule for two machines
Push from the machine you worked on **before** you switch to the other one, and run
`sync-pull-all.sh` on the other machine **before** you start. That keeps both in sync
and avoids diverged histories.
## Helper scripts
| Script | What it does |
|--------|--------------|
| `sync-clone-all.sh` | Clone any module repo listed in `repos.txt` that isn't here yet. |
| `sync-pull-all.sh` | Fast-forward pull the parent + all modules (safe, never clobbers). |
| `sync-push-all.sh` | Push committed work for the parent + all modules to GitHub + gitea. |
| `sync-refresh-list.sh` | Rebuild `repos.txt` from the repos present here (after adding/removing a module). |
| `repos.txt` | The list of module repo names the scripts act on. |

52
repos.txt Normal file
View File

@@ -0,0 +1,52 @@
# Module repos that live as independent git repos inside this folder.
# Owner: github.com/gsinghpal/<name> + gitea git.nexasystems.ca/admin/<name>
# One repo name per line. Used by sync-*.sh. Regenerate with: bash sync-refresh-list.sh
disable_iap_calls
disable_odoo_online
disable_publisher_warranty
fusion_accounts
fusion_api
fusion_canada_post
fusion_centralize_billing
fusion_chatter_enhance
fusion_claims
fusion_clock
fusion_clock_ai
fusion_clover
fusion_digitize
fusion_faxes
fusion_helpdesk
fusion_helpdesk_central
fusion_inventory
fusion_loaners_management
fusion_login_audit
fusion_ltc_management
fusion_notes
fusion_odoo_fixes
fusion_payroll
fusion_pdf_preview
fusion_planning
fusion_portal
fusion_poynt
fusion_rental
fusion_repairs
fusion_reports_templates
fusion_ringcentral
fusion_schedule
fusion_service_charges
fusion_shipping
fusion_so_to_po
fusion_tasks
fusion_templates
fusion_theme_switcher
fusion_voip_ringcentral
fusion_whitelabels
network_logger
nexa_coa_setup
fusion_plating
fusion_accounting
fusion_iot
fusion_labels
fusion_projects
fusion-statements
fusion-woo-odoo

28
sync-clone-all.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Clone every module repo listed in repos.txt into this folder.
# Run once on a new machine, right after you clone the parent Odoo-Modules repo.
# Adds both GitHub (origin) and gitea remotes. Never deletes or overwrites folders.
#
# Mac/Linux: bash sync-clone-all.sh
# Windows : open "Git Bash" here, then: bash sync-clone-all.sh
set -uo pipefail
cd "$(dirname "$0")" || exit 1
GH="https://github.com/gsinghpal"
GITEA="https://git.nexasystems.ca/admin"
[ -f repos.txt ] || { echo "repos.txt not found next to this script"; exit 1; }
cloned=0; skipped=0; failed=0
while IFS= read -r f; do
case "$f" in ''|\#*) continue ;; esac
if [ -d "$f/.git" ]; then
echo "skip (already here): $f"; skipped=$((skipped+1)); continue
fi
if git clone -q "$GH/$f.git" "$f"; then
git -C "$f" remote add gitea "$GITEA/$f.git" 2>/dev/null || true
echo "cloned: $f"; cloned=$((cloned+1))
else
echo "FAILED: $f"; failed=$((failed+1))
fi
done < repos.txt
echo "----------------------------------------"
echo "cloned=$cloned skipped=$skipped failed=$failed"

44
sync-pull-all.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Pull the latest for the parent repo + every module repo.
# Fast-forward only: it NEVER overwrites or deletes your local work. If a repo has
# diverged or has conflicting local changes, it is skipped and reported so you can
# handle it by hand. Clones any module folder that is missing.
# Run this before you start working on a machine.
#
# bash sync-pull-all.sh
set -uo pipefail
cd "$(dirname "$0")" || exit 1
GH="https://github.com/gsinghpal"
GITEA="https://git.nexasystems.ca/admin"
pull_one() {
local d="$1"
local br; br=$(git -C "$d" symbolic-ref --short HEAD 2>/dev/null || echo main)
if git -C "$d" pull --ff-only -q origin "$br" 2>/dev/null; then
echo "updated: $d"
else
if [ -n "$(git -C "$d" status --porcelain --untracked-files=no)" ]; then
echo "SKIP (uncommitted changes block ff): $d -> commit, then re-run"
else
echo "SKIP (diverged, needs manual merge): $d"
fi
fi
}
echo "== parent =="
pull_one .
[ -f repos.txt ] || { echo "repos.txt not found"; exit 1; }
echo "== modules =="
while IFS= read -r f; do
case "$f" in ''|\#*) continue ;; esac
if [ ! -d "$f/.git" ]; then
if git clone -q "$GH/$f.git" "$f"; then
git -C "$f" remote add gitea "$GITEA/$f.git" 2>/dev/null || true
echo "cloned (was missing): $f"
else
echo "FAILED clone: $f"
fi
continue
fi
pull_one "$f"
done < repos.txt

36
sync-push-all.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Push your committed work for the parent + every module repo to BOTH GitHub
# (origin) and gitea. Only commits are pushed. Any repo that still has UNCOMMITTED
# changes is flagged, so you can see exactly what has not been synced yet.
# Run this after you finish working, once you have committed your changes.
#
# bash sync-push-all.sh
set -uo pipefail
cd "$(dirname "$0")" || exit 1
push_one() {
local d="$1"
local br; br=$(git -C "$d" symbolic-ref --short HEAD 2>/dev/null || echo main)
local flag=""
[ -n "$(git -C "$d" status --porcelain --untracked-files=no)" ] && flag=" [HAS UNCOMMITTED CHANGES - not pushed]"
local any=0
for r in origin gitea; do
git -C "$d" remote get-url "$r" >/dev/null 2>&1 || continue
any=1
if git -C "$d" push -q "$r" "$br" 2>/dev/null; then
echo "pushed: $d -> $r$flag"
else
echo "push FAILED (or nothing to push): $d -> $r$flag"
fi
done
[ "$any" = 0 ] && echo "no remotes: $d"
}
echo "== parent =="
push_one .
[ -f repos.txt ] || { echo "repos.txt not found"; exit 1; }
echo "== modules =="
while IFS= read -r f; do
case "$f" in ''|\#*) continue ;; esac
if [ -d "$f/.git" ]; then push_one "$f"; else echo "skip (not cloned): $f"; fi
done < repos.txt

23
sync-refresh-list.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Regenerate repos.txt from the actual module folders present here (any top-level
# folder that is its own git repo with a github.com/gsinghpal origin). Run this
# after you add or remove a module repo, then commit repos.txt so both machines
# pick up the change.
#
# bash sync-refresh-list.sh
set -uo pipefail
cd "$(dirname "$0")" || exit 1
{
echo "# Module repos that live as independent git repos inside this folder."
echo "# Owner: github.com/gsinghpal/<name> + gitea git.nexasystems.ca/admin/<name>"
echo "# One repo name per line. Used by sync-*.sh. Regenerate with: bash sync-refresh-list.sh"
for d in */; do
d="${d%/}"
[ -d "$d/.git" ] || continue
url=$(git -C "$d" remote get-url origin 2>/dev/null || true)
case "$url" in *github.com/gsinghpal/*) echo "$d" ;; esac
done
} > repos.txt.tmp && mv repos.txt.tmp repos.txt
echo "repos.txt now lists $(grep -cvE '^\s*#|^\s*$' repos.txt) repos"