Skip to content

Commit cef9441

Browse files
committed
fix: Release v3.5 - Fix interactive prompts via Array Strategy
Resolves a regression where push/pull confirmation prompts were being skipped. **The Fix:** * Refactored the file iteration logic in `push` and `pull` commands. * Previously, the `while read` loop consumed `stdin`, preventing the `confirm()` function from reading user input during `[y/N]` prompts. * Now loads the target file list into an array first, freeing up `stdin` for interactive prompts. **Changes:** * refactor: Implement "Array Strategy" for file processing to avoid FD conflicts. * fix: Ensure `read -p` works correctly in Zsh/Bash strict modes. * chore: Bump version to 3.5.
1 parent f64ffca commit cef9441

2 files changed

Lines changed: 152 additions & 116 deletions

File tree

README.md

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
**The minimalist's answer to dotfile management.**
44
Sync your shell configurations, editor settings, and scripts to a secret GitHub Gist—securely, instantly, and without the bloat.
55

6-
Now with cross-platform support for **macOS** and **Linux**.
6+
Now with **Interactive Mode**, **Batch Syncing**, and **Cross-Platform Support** (macOS & Linux).
77

88
---
99

1010
## 🎥 See it in action
1111

12-
### 1. Syncing (Push)
13-
*Instant backup of your local settings to the cloud.*
12+
### 1. Interactive Push (Default)
13+
*Review changes file-by-file before uploading.*
1414
![](./resources/dfsync-push.gif)
1515

1616
### 2. First Time Setup
@@ -26,9 +26,9 @@ Most dotfile managers are over-engineered. They force you to move your files, cr
2626
**dotfilesync is different:**
2727
* **📍 Non-Destructive:** Your files stay exactly where they are. No symlinks. No moving files.
2828
* **🔒 Secure by Design:**
29-
* **macOS:** Uses the native **Keychain** to store tokens.
30-
* **Linux:** Uses a secured file with strict read-only permissions.
31-
* **🚀 Zero Friction:** No `git add`, `git commit`, `git push`. Just `dfsync push`.
29+
* **macOS:** Uses native **Keychain** (encrypted at rest).
30+
* **Linux:** Uses a locked-down file (`600` permissions) readable only by you.
31+
* **🤝 Interactive or Automated:** Confirm every file operation manually, or use `-y` for instant batch processing.
3232
* **🛠 Zero Dependencies:** Written in pure Bash. Configuration is a simple JSON file.
3333

3434
---
@@ -37,70 +37,92 @@ Most dotfile managers are over-engineered. They force you to move your files, cr
3737

3838
You do not need to clone this repository. Install the binary directly to your path using `curl`.
3939

40-
```bash
40+
'''bash
4141
mkdir -p ~/.local/bin
4242
curl -fsSL https://raw.githubusercontent.com/snvishna/dotfilesync/master/src/dfsync.sh -o ~/.local/bin/dfsync
4343
chmod +x ~/.local/bin/dfsync
44-
```
44+
'''
4545

4646
> **Note:** Ensure `~/.local/bin` is in your `$PATH`.
4747
4848
### Prerequisites
4949
* **curl** (Standard on most systems)
5050
* **jq** (Required for JSON parsing)
5151

52-
```bash
52+
'''bash
5353
# macOS
5454
brew install jq
5555

5656
# Linux (Ubuntu/Debian)
5757
sudo apt-get install jq
58-
```
58+
'''
5959

6060
---
6161

6262
## 🚦 Quick Start Guide
6363

64-
Follow these four steps to back up your environment in under 2 minutes.
65-
6664
### 1. Connect (Setup)
67-
First, link your machine to GitHub securely. You will need a **GitHub Personal Access Token (Classic)** with **`gist`** scope.
68-
65+
First, link your machine to GitHub. You need a **Personal Access Token (Classic)** with **`gist`** scope.
6966
* [Generate Token Here](https://github.com/settings/tokens/new?scopes=gist&description=dotfilesync)
7067

7168
Run the setup wizard:
72-
```bash
69+
'''bash
7370
dfsync setup
74-
```
75-
*Tip: Use `dfsync setup -y` to automatically accept default config paths.*
71+
'''
72+
*(Use `dfsync setup -y` to auto-accept default config paths).*
7673

7774
![](https://github.com/snvishna/dotfilesync/blob/master/resources/generate_personal_access_token.gif)
7875

7976
### 2. Track Files
80-
Tell dfsync which files you want to manage. You can track individual files from anywhere in your home directory.
77+
Tell dfsync which files you want to manage.
8178

82-
```bash
83-
# Track your Zsh config
79+
'''bash
8480
dfsync track ~/.zshrc
85-
86-
# Track your Starship prompt config
8781
dfsync track ~/.config/starship.toml
88-
```
82+
'''
8983

9084
### 3. Sync (Push)
91-
Upload your tracked files to the cloud. If you don't have a Gist yet, this command creates one for you automatically.
85+
Upload your tracked files.
9286

93-
```bash
87+
**Interactive Mode (Safest):**
88+
'''bash
9489
dfsync push
95-
```
90+
# Prompts: "Upload /Users/me/.zshrc? [y/N]"
91+
'''
92+
93+
**Batch Mode (Fastest):**
94+
'''bash
95+
dfsync push -y
96+
# Uploads everything immediately.
97+
'''
9698

9799
### 4. Restore (Pull)
98-
On a new machine (or if you accidentally delete a config), download the latest version from your Gist.
100+
On a new machine, download your configs.
99101

100-
```bash
102+
'''bash
101103
dfsync pull
102-
```
103-
*⚠️ Warning: This overwrites your local files with the version from the Gist.*
104+
'''
105+
*Prompts you before overwriting any local file, unless you use `-y`.*
106+
107+
---
108+
109+
## 🛠 CLI Reference
110+
111+
Flags can be placed anywhere (e.g., `dfsync -y push` or `dfsync push -y`).
112+
113+
| Command | Usage | Description |
114+
| :--- | :--- | :--- |
115+
| **setup** | `dfsync setup [-y]` | Initialize token and config. |
116+
| **track** | `dfsync track <file>` | Add a file to the sync list. |
117+
| **untrack** | `dfsync untrack <file>` | Remove a file from the sync list. |
118+
| **push** | `dfsync push [-y] [-v]` | Upload files. Default is interactive. `-y` auto-confirms. |
119+
| **pull** | `dfsync pull [-y] [-v]` | Download files. Default is interactive. `-y` auto-confirms. |
120+
| **config** | `dfsync config token` | Update your GitHub Access Token. |
121+
| **help** | `dfsync help` | Show usage guide. |
122+
123+
**Global Options:**
124+
* `-y`, `--yes`: Non-interactive mode. Auto-answers "yes" to all prompts.
125+
* `-v`, `--verbose`: Enable detailed debug logs (HTTP status, payload sizes, etc).
104126

105127
---
106128

@@ -110,7 +132,7 @@ dfsync uses a single JSON file to track your state.
110132
**Default Location:** `~/.config/dfsync.json`
111133

112134
### The Config Structure
113-
```json
135+
'''json
114136
{
115137
"gist_id": "8f3... (Auto-generated)",
116138
"files": [
@@ -119,44 +141,22 @@ dfsync uses a single JSON file to track your state.
119141
"~/.vimrc"
120142
]
121143
}
122-
```
123-
You can edit this file manually if you prefer, or use the CLI commands (`track`/`untrack`) to manage it.
124-
125-
> **Legacy Support:** If you are upgrading from an older version, your existing config (`dotFilePaths` / `gistId`) works automatically.
126-
127-
---
128-
129-
## 🛠 CLI Reference
130-
131-
| Command | Usage | Description |
132-
| :--- | :--- | :--- |
133-
| **setup** | `dfsync setup [-y]` | Initialize token and config. `-y` accepts defaults. |
134-
| **track** | `dfsync track <file>` | Add a file to the sync list. |
135-
| **untrack** | `dfsync untrack <file>` | Remove a file from the sync list. |
136-
| **push** | `dfsync push [-v]` | Upload tracked files. `-v` shows detailed logs. |
137-
| **pull** | `dfsync pull [-v]` | Download files from Gist. `-v` shows detailed logs. |
138-
| **config token** | `dfsync config token` | Update your GitHub Access Token. |
139-
| **config path** | `dfsync config path` | Change the location of the `dfsync.json` file. |
140-
| **help** | `dfsync help` | Show usage guide. |
144+
'''
145+
> **Note:** Backward compatibility with older config schemas (`dotFilePaths`, `gistId`) is built-in.
141146
142147
---
143148

144149
## 🧠 Deep Dive
145150

146151
### Security Model
147-
Unlike tools that store API tokens in plain text (`~/.npmrc`, `~/.git-credentials`), dotfilesync prioritizes security.
148-
149152
* **macOS:** Uses the native **Keychain** (Service: `dotfilesync`). The token is encrypted and only accessible when your Mac is unlocked.
150-
* **Linux:** Stores the token in `~/.dfsync_token` with strict `600` permissions (read/write only by the owner).
153+
* **Linux:** Stores the token in `~/.dfsync_token`. The script enforces `chmod 600` on this file, meaning no other user on the system can read it.
151154

152155
### The "Flattening" Strategy
153-
GitHub Gists do not support folders—they are flat lists of files. To support deep directory structures (like `~/.config/nvim/init.lua`), dotfilesync "flattens" filenames during upload using a double underscore delimiter (`__`).
154-
156+
GitHub Gists do not support folders. To support deep directory structures (like `~/.config/nvim/init.lua`), dotfilesync "flattens" filenames during upload using a double underscore delimiter (`__`).
155157
* **Local:** `~/.config/nvim/init.lua`
156158
* **Gist:** `_config__nvim__init.lua`
157159

158-
When you `pull`, the script intelligently reverses this transformation to restore files to their correct folders.
159-
160160
---
161161

162162
## ❓ Troubleshooting
@@ -167,8 +167,11 @@ The script depends on `jq` to parse JSON. Install it via Homebrew (`brew install
167167
**"Token not found"**
168168
If you upgraded from v1, run `dfsync config token <paste_token>` to migrate your token to the new secure storage.
169169

170-
**"404 Not Found" during Push**
171-
Ensure your GitHub Token has the **`gist`** scope enabled. If the token is invalid, generate a new one and update it using `dfsync config token`.
170+
**Script crashes or weird errors?**
171+
Run with verbose mode to see exactly what's happening:
172+
'''bash
173+
dfsync push -v
174+
'''
172175

173176
---
174177

0 commit comments

Comments
 (0)