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:
58
SYNC.md
Normal file
58
SYNC.md
Normal 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
52
repos.txt
Normal 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
28
sync-clone-all.sh
Executable 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
44
sync-pull-all.sh
Executable 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
36
sync-push-all.sh
Executable 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
23
sync-refresh-list.sh
Executable 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"
|
||||
Reference in New Issue
Block a user