-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdotmng
executable file
·318 lines (287 loc) · 10.6 KB
/
dotmng
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
#!/bin/bash
# Set up variables
HOME_DIR="$HOME"
REPO_DIR="$HOME_DIR/dotfiles"
TRACK_FILE="$REPO_DIR/.track"
CONFIG_FILE="$HOME_DIR/.mng_config" # Configuration file for sync preferences
DEPENDENCIES=("git" "pacman" "rsync")
# Default sync settings if CONFIG_FILE does not exist
SYNC_ON_LOGIN=false
SYNC_ON_LOGOFF=false
# Load configuration file if it exists
load_config() {
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
fi
}
# Save configuration to file
save_config() {
echo "SYNC_ON_LOGIN=$SYNC_ON_LOGIN" > "$CONFIG_FILE"
echo "SYNC_ON_LOGOFF=$SYNC_ON_LOGOFF" >> "$CONFIG_FILE"
echo "Configuration saved to $CONFIG_FILE."
}
# Check for and install necessary dependencies
install_dependencies() {
echo "Checking and installing necessary dependencies..."
for cmd in "${DEPENDENCIES[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
echo "$cmd is not installed. Installing..."
sudo pacman -S --noconfirm "$cmd" || {
echo "Error: Unable to install $cmd. Please check your pacman setup."
exit 1
}
fi
done
# Check for yay and prompt to install if missing
if ! command -v yay &> /dev/null; then
echo "yay (AUR helper) is not installed. Installing yay is recommended for full functionality."
read -p "Would you like to install yay? (y/n): " install_yay
if [[ "$install_yay" =~ ^[Yy]$ ]]; then
git clone https://aur.archlinux.org/yay.git /tmp/yay && cd /tmp/yay
makepkg -si --noconfirm || {
echo "Error: Unable to install yay. Please install manually if needed."
exit 1
}
cd "$REPO_DIR" || exit
fi
fi
echo "All dependencies are installed."
}
# Function to initialize necessary files and directories
initialize_files() {
echo "Initializing necessary files and directories..."
# Ensure REPO_DIR exists
[ -d "$REPO_DIR" ] || mkdir -p "$REPO_DIR" || {
echo "Error: Unable to create repository directory $REPO_DIR."
exit 1
}
# Create TRACK_FILE if it doesn't exist
[ -f "$TRACK_FILE" ] || touch "$TRACK_FILE" || {
echo "Error: Unable to create .track file."
exit 1
}
echo "Created .track file for tracking specific files and directories."
# Create packages.txt if it doesn't exist
[ -f "$REPO_DIR/packages.txt" ] || touch "$REPO_DIR/packages.txt" || {
echo "Error: Unable to create packages.txt file."
exit 1
}
echo "Created packages.txt for package tracking."
echo "Initialization complete."
}
# Function to handle package installation from packages.txt
install_packages() {
if [ -f "$REPO_DIR/packages.txt" ]; then
echo "Installing packages listed in packages.txt..."
while IFS= read -r package; do
if pacman -Qi "$package" &>/dev/null || yay -Qi "$package" &>/dev/null; then
echo "$package is already installed."
else
yay -S --noconfirm "$package" || pacman -S --noconfirm "$package" || {
echo "Error: Failed to install $package."
exit 1
}
fi
done < "$REPO_DIR/packages.txt"
else
echo "Error: packages.txt not found in $REPO_DIR."
exit 1
fi
}
# Function to copy only tracked files from .track
copy_tracked_files() {
echo "Copying files and directories listed in .track from $REPO_DIR to $HOME_DIR..."
while IFS= read -r item; do
if [ -n "$item" ] && [ -e "$REPO_DIR/$item" ]; then
target_dir="$HOME_DIR/$(dirname "$item")"
mkdir -p "$target_dir" || {
echo "Error: Failed to create target directory $target_dir."
exit 1
}
echo "Copying $item..."
rsync -av "$REPO_DIR/$item" "$target_dir" || {
echo "Error: Failed to copy $item."
exit 1
}
fi
done < "$TRACK_FILE"
echo "File copying complete."
}
# Function to handle commits and pushes
commit_and_push() {
local message="$1"
cd "$REPO_DIR" || { echo "Error: Unable to access repository directory."; exit 1; }
git add . || { echo "Error: Failed to stage changes."; exit 1; }
git commit -m "$message" || { echo "Error: Failed to commit changes."; exit 1; }
git push || { echo "Error: Failed to push changes to remote."; exit 1; }
echo "Changes committed and pushed with message: $message"
}
# Function for -up option: Update repository with changes from home
update_repo() {
echo "Updating repository with changes from $HOME_DIR..."
while IFS= read -r item; do
if [ -n "$item" ] && [ -e "$HOME_DIR/$item" ]; then
target_dir="$REPO_DIR/$(dirname "$item")"
mkdir -p "$target_dir" || {
echo "Error: Failed to create target directory $target_dir."
exit 1
}
echo "Copying $item from $HOME_DIR to $REPO_DIR"
rsync -av "$HOME_DIR/$item" "$target_dir" || {
echo "Error: Failed to copy $item."
exit 1
}
fi
done < "$TRACK_FILE"
echo "Saving list of installed packages to packages.txt..."
pacman -Qq > "$REPO_DIR/packages.txt" || {
echo "Error: Failed to generate package list."
exit 1
}
if command -v yay &> /dev/null; then
yay -Qq >> "$REPO_DIR/packages.txt" || {
echo "Error: Failed to add AUR packages to package list."
exit 1
}
fi
commit_and_push "Updated from 'dconf -up' at $(date +'%Y-%m-%d %H:%M:%S')"
}
# Function for -setup option: Initial setup on a new system
setup() {
# Prompt for a Git repository URL
read -p "Enter the Git repository URL to track: " repo_url
if [ -z "$repo_url" ]; then
echo "Error: No repository URL provided. Exiting setup."
exit 1
fi
# Check if the directory exists and is already a Git repository
if [ -d "$REPO_DIR/.git" ]; then
echo "Directory $REPO_DIR already exists as a Git repository."
# Check if it has the correct remote URL
current_remote=$(git -C "$REPO_DIR" remote get-url origin 2>/dev/null)
if [ "$current_remote" != "$repo_url" ]; then
echo "Current remote URL ($current_remote) differs from the specified URL."
read -p "Would you like to update the remote to $repo_url? (y/n): " update_remote
if [[ "$update_remote" =~ ^[Yy]$ ]]; then
git -C "$REPO_DIR" remote set-url origin "$repo_url"
echo "Remote updated to $repo_url."
else
echo "Remote URL not changed."
fi
fi
else
# Clone the repository if it doesn’t exist locally
if git clone "$repo_url" "$REPO_DIR"; then
echo "Repository cloned successfully to $REPO_DIR."
else
echo "Error: Failed to clone the repository. Exiting setup."
exit 1
fi
fi
install_dependencies
initialize_files
install_packages
copy_tracked_files
echo "Setup complete."
}
# Function for -r option: Pull changes from the cloud and apply to home
pull_and_apply() {
echo "Pulling updates from the remote repository..."
cd "$REPO_DIR" || { echo "Error: Unable to access repository directory."; exit 1; }
git pull || { echo "Error: Failed to pull updates from remote."; exit 1; }
copy_tracked_files
echo "Remote updates applied to home directory."
}
# Function for -add option: Add new directories to track in the repository
add_to_repo() {
for item in "$@"; do
if [ -e "$HOME_DIR/$item" ]; then
if ! grep -Fxq "$item" "$TRACK_FILE"; then
echo "$item" >> "$TRACK_FILE"
echo "$item added to .track"
else
echo "$item is already listed in .track"
fi
target_dir="$REPO_DIR/$(dirname "$item")"
mkdir -p "$target_dir" || {
echo "Error: Failed to create target directory $target_dir."
exit 1
}
rsync -av "$HOME_DIR/$item" "$target_dir" || {
echo "Error: Failed to copy $item."
exit 1
}
commit_and_push "Added $item to tracking"
else
echo "Error: $item does not exist in $HOME_DIR"
fi
done
}
# Function for -ignore option: Remove an item from .track and untrack in the repository
ignore_and_remove() {
for item in "$@"; do
echo "Ignoring $item by removing from .track and repository if tracked..."
if grep -Fxq "$item" "$TRACK_FILE"; then
sed -i "/^$item$/d" "$TRACK_FILE" || { echo "Error: Failed to remove $item from .track."; exit 1; }
echo "$item removed from .track."
else
echo "$item is not listed in .track."
fi
if git -C "$REPO_DIR" ls-files --error-unmatch "$item" &> /dev/null; then
git -C "$REPO_DIR" rm -r --cached "$item" || { echo "Error: Failed to untrack $item from Git."; exit 1; }
echo "$item removed from repository tracking."
fi
commit_and_push "Ignored and removed $item from tracking"
done
}
# Function for -clone option: Set up on a new machine from a cloned repository
clone_setup() {
# Prompt for a Git repository URL
read -p "Enter the Git repository URL to track: " repo_url
if [ -z "$repo_url" ]; then
echo "Error: No repository URL provided. Exiting clone setup."
exit 1
fi
# Clone the repository into REPO_DIR
if git clone "$repo_url" "$REPO_DIR"; then
echo "Repository cloned successfully to $REPO_DIR."
else
echo "Error: Failed to clone the repository. Exiting clone setup."
exit 1
fi
install_packages
copy_tracked_files
echo "Clone setup complete. Dotfiles and configurations copied to $HOME_DIR."
}
# Ensure dependencies and files are ready for all commands except -setup and -clone
if [[ "$1" != "-setup" && "$1" != "-clone" ]]; then
install_dependencies
[ -f "$TRACK_FILE" ] || { echo "Error: .track file missing. Run -setup or -clone first."; exit 1; }
fi
# Parse command-line arguments
case "$1" in
-up)
update_repo
;;
-setup)
setup
;;
-r)
pull_and_apply
;;
-add)
shift
add_to_repo "$@"
;;
-ignore)
shift
ignore_and_remove "$@"
;;
-clone)
clone_setup
;;
*)
echo "Usage: $0 {-up|-setup|-r|-add <file_or_dir> ...|-ignore <file_or_dir> ...|-clone}"
exit 1
;;
esac