Skip to content

Commit fa78db3

Browse files
committed
Initial project setup and migration scripts
Add one-shot-migrate data-only macOS migration helper, including main migration script, double-clickable installer, exclusion presets, documentation, changelog, release workflow, and license. Provides guided user experience, exclusion management, and checksum verification for safe user data migration.
1 parent 6a6b746 commit fa78db3

14 files changed

Lines changed: 585 additions & 0 deletions

.github/workflows/release.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Build and attach release zip
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
build-release-zip:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
15+
- name: Create release zip
16+
run: |
17+
set -e
18+
VERSION="${GITHUB_REF_NAME}"
19+
ZIP="one-shot-migrate-${VERSION}.zip"
20+
mkdir -p dist
21+
zip -r "dist/${ZIP}" one-shot-migrate
22+
23+
- name: Create GitHub Release and upload asset
24+
env:
25+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
run: |
27+
set -e
28+
VERSION="${GITHUB_REF_NAME}"
29+
ZIP="one-shot-migrate-${VERSION}.zip"
30+
gh release create "${VERSION}" "dist/${ZIP}" --title "${VERSION}" --notes-file "one-shot-migrate/RELEASE_NOTES.md" || \
31+
gh release upload "${VERSION}" "dist/${ZIP}" --clobber

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Runtime outputs
2+
migration_logs/
3+
one_shot_run.out
4+
*.log
5+
6+
# macOS junk
7+
.DS_Store
8+
._*
9+
10+
# Editor/IDE
11+
.idea/
12+
.vscode/

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Changelog
2+
3+
## v1.1.1 — 2026-01-16
4+
- ZIP-first GitHub packaging cleanup (no DMG).
5+
- Added `presets/` with example exclusion sets.
6+
- Improved `Install.command` with preset chooser and background-run option.
7+
- Docs refreshed to match repo name `one-shot-migrate`.
8+
9+
## v1.1.0
10+
- Initial dialog-driven launcher.

INSTRUCTIONS.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# INSTRUCTIONS — one-shot-migrate (v1.1.1)
2+
3+
## Dialog run (recommended)
4+
Double-click **Install.command** and follow prompts (preset, edit excludes, DRYRUN/RUN, VERIFY, background run).
5+
6+
## Terminal run
7+
8+
```bash
9+
chmod +x ./one-shot-migrate.sh
10+
cd ~/one-shot-migrate
11+
DRYRUN=1 ./one-shot-migrate.sh
12+
nohup ./one-shot-migrate.sh > ~/migration_logs/one_shot_run.out 2>&1 &
13+
tail -n 80 ~/migration_logs/one_shot_run.out
14+
tail -f ~/migration_logs/one_shot_run.out
15+
```
16+
17+
Stop:
18+
```bash
19+
pkill -f one-shot-migrate.sh
20+
pkill -f rsync
21+
```
22+
23+
Resume:
24+
```bash
25+
cd ~/one-shot-migrate
26+
nohup ./one-shot-migrate.sh > ~/migration_logs/one_shot_run.out 2>&1 &
27+
```
28+
29+
Verification:
30+
```bash
31+
VERIFY=1 ./one-shot-migrate.sh
32+
VERIFY=0 ./one-shot-migrate.sh
33+
```
34+
35+
Presets:
36+
```bash
37+
cp -f ./presets/developer-heavy.txt ./exclude.txt
38+
open -t ./exclude.txt
39+
```
40+
41+
Troubleshooting:
42+
```bash
43+
xcode-select --install
44+
```

Install.command

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/bin/bash
2+
# Install.command — v1.1.1
3+
# Double-clickable launcher for macOS (Finder).
4+
set -euo pipefail
5+
6+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7+
cd "$SCRIPT_DIR"
8+
9+
chmod +x ./one-shot-migrate.sh 2>/dev/null || true
10+
11+
has_osascript=0
12+
command -v osascript >/dev/null 2>&1 && has_osascript=1
13+
14+
choose_preset() {
15+
if [[ "$has_osascript" == "1" ]]; then
16+
osascript <<'OSA'
17+
set choices to {"Keep current exclude.txt","minimal (Library + macOS metadata)","developer-heavy (skip caches)","media-keeper (keep project deps)"}
18+
set c to choose from list choices with prompt "Pick an exclusion preset (you can edit later):" default items {"Keep current exclude.txt"}
19+
if c is false then return "KEEP"
20+
set v to item 1 of c
21+
if v is "Keep current exclude.txt" then return "KEEP"
22+
if v is "minimal (Library + macOS metadata)" then return "minimal.txt"
23+
if v is "developer-heavy (skip caches)" then return "developer-heavy.txt"
24+
if v is "media-keeper (keep project deps)" then return "media-keeper.txt"
25+
return "KEEP"
26+
OSA
27+
else
28+
echo "Pick an exclusion preset:"
29+
echo " 1) Keep current exclude.txt"
30+
echo " 2) minimal"
31+
echo " 3) developer-heavy"
32+
echo " 4) media-keeper"
33+
read -r -p "Choose [1-4]: " n
34+
case "${n:-1}" in
35+
2) echo "minimal.txt" ;;
36+
3) echo "developer-heavy.txt" ;;
37+
4) echo "media-keeper.txt" ;;
38+
*) echo "KEEP" ;;
39+
esac
40+
fi
41+
}
42+
43+
ask_yesno() {
44+
local prompt="$1"
45+
local default="$2"
46+
if [[ "$has_osascript" == "1" ]]; then
47+
osascript <<OSA
48+
display dialog "$prompt" buttons {"No","Yes"} default button "$default"
49+
button returned of result
50+
OSA
51+
else
52+
read -r -p "$prompt (y/N): " yn
53+
[[ "$yn" =~ ^[Yy]$ ]] && echo "Yes" || echo "No"
54+
fi
55+
}
56+
57+
ask_mode() {
58+
if [[ "$has_osascript" == "1" ]]; then
59+
osascript <<'OSA'
60+
set choices to {"DRYRUN","RUN"}
61+
set c to choose from list choices with prompt "Choose run mode:" default items {"DRYRUN"}
62+
if c is false then return "DRYRUN"
63+
return item 1 of c
64+
OSA
65+
else
66+
echo "Choose run mode:"
67+
echo " 1) DRYRUN (preview only)"
68+
echo " 2) RUN (real copy)"
69+
read -r -p "Choose [1-2]: " n
70+
[[ "${n:-1}" == "2" ]] && echo "RUN" || echo "DRYRUN"
71+
fi
72+
}
73+
74+
preset="$(choose_preset)"
75+
if [[ "$preset" != "KEEP" ]]; then
76+
cp -f "./presets/$preset" ./exclude.txt
77+
fi
78+
79+
edit="$(ask_yesno "Do you want to edit exclude.txt now?" "Yes")"
80+
if [[ "$edit" == "Yes" ]]; then
81+
open -t ./exclude.txt || true
82+
fi
83+
84+
mode="$(ask_mode)"
85+
verify="$(ask_yesno "Enable checksum verification after copy?" "Yes")"
86+
bg="$(ask_yesno "Run in background (recommended for many files)?" "Yes")"
87+
88+
export DRYRUN=0
89+
export VERIFY=1
90+
[[ "$mode" == "DRYRUN" ]] && export DRYRUN=1
91+
[[ "$verify" == "No" ]] && export VERIFY=0
92+
93+
echo ""
94+
echo "Mode: DRYRUN=$DRYRUN VERIFY=$VERIFY"
95+
echo ""
96+
97+
if [[ "$bg" == "Yes" && "$DRYRUN" == "0" ]]; then
98+
mkdir -p "$HOME/migration_logs"
99+
nohup ./one-shot-migrate.sh > "$HOME/migration_logs/one_shot_run.out" 2>&1 &
100+
msg="Migration started in background.\n\nLog: ~/migration_logs/one_shot_run.out\n\nFollow: tail -f ~/migration_logs/one_shot_run.out"
101+
echo "$msg"
102+
[[ "$has_osascript" == "1" ]] && osascript -e "display dialog \"$msg\" buttons {\"OK\"} default button \"OK\""
103+
exit 0
104+
fi
105+
106+
./one-shot-migrate.sh

MIT License.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Stephen Kinzey
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# one-shot-migrate (v1.1.1)
2+
3+
Data-only macOS user migration helper.
4+
5+
- Prompts for OLD + NEW usernames
6+
- Copies: Desktop, Documents, Downloads, Pictures, Movies, Music
7+
- Skips `~/Library` by default to avoid dragging broken per-user state
8+
- Guided UX via **Install.command**
9+
- Optional checksum verification pass (default on)
10+
11+
## Quick start using Terminal
12+
```bash
13+
chmod +x ./one-shot-migrate.sh
14+
DRYRUN=1 ./one-shot-migrate.sh
15+
nohup ./one-shot-migrate.sh > ~/migration_logs/one_shot_run.out 2>&1 &
16+
tail -n 80 ~/migration_logs/one_shot_run.out
17+
```
18+
19+
## License
20+
MIT License. See the LICENSE file for details.

RELEASE_NOTES.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Release Notes — v1.1.1
2+
3+
Release date: 2026-01-16
4+
5+
## What’s new
6+
- Exclusion presets added under `presets/`.
7+
- Install.command supports:
8+
- preset selection
9+
- optional exclude.txt editor
10+
- DRYRUN vs RUN
11+
- VERIFY toggle
12+
- background run option
13+
14+
## User flow
15+
1. Download ZIP from GitHub Releases
16+
2. Unzip
17+
3. Double-click Install.command
18+
4. Follow prompts

exclude.txt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# exclude.txt — rsync excludes (one pattern per line)
2+
# Lines starting with # are comments.
3+
# Edit this file to control what is skipped during migration.
4+
# Tip: you can swap in a preset from presets/*.txt
5+
6+
# AppleDouble / Finder metadata sidecars
7+
._*
8+
._.
9+
._
10+
.DS_Store
11+
12+
# IMPORTANT: do NOT migrate user Library (this is where per-user state/corruption lives)
13+
Library
14+
15+
# Common dev junk / caches
16+
node_modules
17+
.git
18+
.svn
19+
.hg
20+
vendor
21+
.cache
22+
Caches
23+
.npm
24+
.yarn
25+
.pnpm-store
26+
.composer
27+
.gradle
28+
.parcel-cache
29+
.next
30+
.nuxt
31+
.expo
32+
.terraform
33+
.vscode
34+
.idea
35+
36+
# macOS system stuff
37+
.Spotlight-V100
38+
.Trashes
39+
.Trash
40+
.fseventsd

0 commit comments

Comments
 (0)