-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·152 lines (126 loc) · 5.05 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·152 lines (126 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env bash
# Bootstrap a new project from rust-python-template.
#
# Prompts for the project name (hyphenated, Rust crate convention), author,
# email, and GitHub owner. Renames the crates, the Python package, and the
# metadata across files. Runs `uv sync`, creates the initial commit, then
# self-deletes.
set -euo pipefail
TEMPLATE_PROJECT_NAME="rust-python-template"
TEMPLATE_PACKAGE_NAME="rust_python_template"
TEMPLATE_AUTHOR_NAME="Noé Fontana"
TEMPLATE_AUTHOR_EMAIL="noe.fontana.pro@gmail.com"
TEMPLATE_GITHUB_OWNER="NoeFontana"
echo "Welcome to the rust-python-template bootstrap script."
echo "Press Enter to keep the default value shown in [brackets]."
echo
read -rp "Project name (hyphen-case, e.g., my-cool-lib) [${TEMPLATE_PROJECT_NAME}]: " project_name
project_name=${project_name:-${TEMPLATE_PROJECT_NAME}}
default_package=$(echo "${project_name}" | tr '-' '_')
read -rp "Python package name (snake_case) [${default_package}]: " project_package
project_package=${project_package:-${default_package}}
read -rp "Author name [${TEMPLATE_AUTHOR_NAME}]: " author_name
author_name=${author_name:-${TEMPLATE_AUTHOR_NAME}}
read -rp "Author email [${TEMPLATE_AUTHOR_EMAIL}]: " author_email
author_email=${author_email:-${TEMPLATE_AUTHOR_EMAIL}}
read -rp "GitHub owner (user or org) [${TEMPLATE_GITHUB_OWNER}]: " github_owner
github_owner=${github_owner:-${TEMPLATE_GITHUB_OWNER}}
cat <<EOF
Bootstrapping with:
project name: ${project_name}
python package: ${project_package}
author: ${author_name} <${author_email}>
github owner: ${github_owner}
EOF
read -rp "Proceed? [y/N] " confirm
case "${confirm}" in
[yY]|[yY][eE][sS]) ;;
*) echo "Aborted."; exit 1 ;;
esac
# --- Rename crate directories ---
if [[ "${project_name}" != "${TEMPLATE_PROJECT_NAME}" ]]; then
echo "Renaming crate directories..."
if [[ -d "crates/${TEMPLATE_PROJECT_NAME}-core" ]]; then
mv "crates/${TEMPLATE_PROJECT_NAME}-core" "crates/${project_name}-core"
fi
if [[ -d "crates/${TEMPLATE_PROJECT_NAME}-ffi" ]]; then
mv "crates/${TEMPLATE_PROJECT_NAME}-ffi" "crates/${project_name}-ffi"
fi
fi
# --- Rename Python package directory ---
if [[ "${project_package}" != "${TEMPLATE_PACKAGE_NAME}" && -d "python/${TEMPLATE_PACKAGE_NAME}" ]]; then
echo "Renaming Python package directory..."
mv "python/${TEMPLATE_PACKAGE_NAME}" "python/${project_package}"
fi
# --- Replace tokens across project files ---
# Token replacements are applied in dependency order: most specific first, so
# we don't accidentally double-substitute (e.g., the package name appears
# inside the hyphenated project name).
replace_in_files() {
local search=$1
local replace=$2
# Skip .git, target, .venv, node_modules, this script, uv.lock, and the
# binary lock files. Use grep -l to limit sed to files actually containing
# the search string, which keeps the run fast and avoids touching binaries.
local files
files=$(grep -rlF "${search}" . \
--exclude-dir=.git \
--exclude-dir=target \
--exclude-dir=.venv \
--exclude-dir=node_modules \
--exclude-dir=__pycache__ \
--exclude-dir=dist \
--exclude=setup.sh \
--exclude=uv.lock \
--exclude=Cargo.lock \
2>/dev/null || true)
if [[ -z "${files}" ]]; then
return 0
fi
if [[ "${OSTYPE:-}" == "darwin"* ]]; then
echo "${files}" | xargs sed -i '' "s|${search}|${replace}|g"
else
echo "${files}" | xargs sed -i "s|${search}|${replace}|g"
fi
}
echo "Updating project files..."
if [[ "${project_package}" != "${TEMPLATE_PACKAGE_NAME}" ]]; then
replace_in_files "${TEMPLATE_PACKAGE_NAME}" "${project_package}"
fi
if [[ "${project_name}" != "${TEMPLATE_PROJECT_NAME}" ]]; then
replace_in_files "${TEMPLATE_PROJECT_NAME}" "${project_name}"
fi
if [[ "${github_owner}" != "${TEMPLATE_GITHUB_OWNER}" ]]; then
replace_in_files "${TEMPLATE_GITHUB_OWNER}" "${github_owner}"
fi
if [[ "${author_email}" != "${TEMPLATE_AUTHOR_EMAIL}" ]]; then
replace_in_files "${TEMPLATE_AUTHOR_EMAIL}" "${author_email}"
fi
if [[ "${author_name}" != "${TEMPLATE_AUTHOR_NAME}" ]]; then
replace_in_files "${TEMPLATE_AUTHOR_NAME}" "${author_name}"
fi
# --- Sync the venv ---
if command -v uv >/dev/null 2>&1; then
echo "Running uv sync..."
uv sync
else
echo "Warning: 'uv' not found on PATH; skipping 'uv sync'. Install uv from https://docs.astral.sh/uv/ and run 'just bootstrap'."
fi
# --- Create the initial commit ---
if [[ -d ".git" ]]; then
echo "Creating initial commit..."
git add -A
git commit -m "chore: bootstrap from rust-python-template" || \
echo "Note: nothing to commit, repository already clean."
else
echo "Warning: not a git repository; skipping initial commit."
fi
# --- Self-delete ---
echo "Removing bootstrap script."
rm -- "$0"
cat <<EOF
Done. Next steps:
1. Review the diff: git log -1 --stat
2. Run the test suite: just bootstrap && just test
3. Push to your remote: git remote add origin git@github.com:${github_owner}/${project_name}.git && git push -u origin main
EOF