diff --git a/README.md b/README.md index 6ea9555..a91361e 100644 --- a/README.md +++ b/README.md @@ -58,12 +58,17 @@ git volume status ## 📖 Commands -| Command | Description | -| ------------------- | -------------------------------------------------------- | -| `git volume init` | Create global directory and sample configuration file | -| `git volume sync` | Mount volumes to current worktree based on configuration | -| `git volume unsync` | Remove mounted volumes (modified files are preserved) | -| `git volume status` | Display current volume status | +| Command | Description | +| -------------------------- | -------------------------------------------------------- | +| `git volume init` | Create global directory and sample configuration file | +| `git volume sync` | Mount volumes to current worktree based on configuration | +| `git volume unsync` | Remove mounted volumes (modified files are preserved) | +| `git volume status` | Display current volume status | +| `git volume global add` | Copy files to global storage (`~/.git-volume`) | +| `git volume global list` | List files in global storage (tree view) | +| `git volume global edit` | Edit a file in global storage with `$EDITOR` | +| `git volume global remove` | Remove files from global storage (alias: `rm`) | +| `git volume version` | Print version information | ## ⚙️ Configuration File (`git-volume.yaml`) @@ -76,6 +81,12 @@ volumes: - mount: "secrets/prod.key:config/prod.key" mode: "copy" # link (default) or copy + # Mount from global storage (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Directory mount (copies entire directory) + - mount: "configs:app/configs" + mode: "copy" ``` ### Mode Comparison @@ -102,12 +113,48 @@ cd ../feature-branch git volume sync # uses parent's git-volume.yaml ``` +## 🌐 Global Storage + +Global storage (`~/.git-volume`) allows sharing files across multiple projects using the `@global/` prefix. + +```bash +# Add files to global storage +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# List, edit, and remove +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +Use `@global/` in your configuration to reference these files: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 CLI Options + +| Flag | Commands | Description | +| ----------------- | ---------------- | ---------------------------------------------- | +| `--dry-run` | `sync`, `unsync` | Show what would be done without making changes | +| `--relative` | `sync` | Create relative symlinks instead of absolute | +| `--verbose`, `-v` | All | Verbose output | +| `--quiet`, `-q` | All | Suppress non-error output | +| `--config`, `-c` | All | Custom config file path | + ## 🛡️ Safety Features - **Symlink Source Rejection**: `sync` and `global add` reject symlink sources for security -- **Change Detection on Unsync**: Files copied in copy mode are preserved if modified -- **Change Detection on Status (Copy Mode)**: `status` reports `MODIFIED` when copied targets differ from source -- **Idempotent**: Running `sync` multiple times is safe +- **Path Traversal Prevention**: All paths are validated to prevent directory escape attacks +- **Change Detection on Unsync**: Copied files and directories are preserved if modified +- **Change Detection on Status**: `status` reports `MODIFIED` when copied targets differ from source +- **Idempotent Sync**: Running `sync` multiple times always produces the same result ## 📄 License diff --git a/cmd/root.go b/cmd/root.go index 3f0b233..e645b7c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -22,7 +22,6 @@ var rootCmd = &cobra.Command{ by dynamically mounting them using a git-volume.yaml manifest. "Keep code in Git, mount environments as volumes."`, - SilenceErrors: true, } // Execute adds all child commands to the root command and sets flags appropriately. diff --git a/cmd/sync.go b/cmd/sync.go index 24978e9..d55ef3d 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -9,7 +9,7 @@ import ( ) var ( - dryRun bool + syncDryRun bool relativeLinks bool ) @@ -34,7 +34,7 @@ it looks for it in the main Git worktree (inheritance).`, } return gv.Sync(gitvolume.SyncOptions{ - DryRun: dryRun, + DryRun: syncDryRun, RelativeLinks: relativeLinks, }) }, @@ -42,6 +42,6 @@ it looks for it in the main Git worktree (inheritance).`, func init() { rootCmd.AddCommand(syncCmd) - syncCmd.Flags().BoolVar(&dryRun, "dry-run", false, "show what would be done without making changes") + syncCmd.Flags().BoolVar(&syncDryRun, "dry-run", false, "show what would be done without making changes") syncCmd.Flags().BoolVar(&relativeLinks, "relative", false, "create relative symlinks instead of absolute") } diff --git a/cmd/unsync.go b/cmd/unsync.go index a735616..8a17cd9 100644 --- a/cmd/unsync.go +++ b/cmd/unsync.go @@ -8,6 +8,9 @@ import ( "github.com/spf13/cobra" ) +// unsyncDryRun is the local flag for the unsync command +var unsyncDryRun bool + // unsyncCmd represents the unsync command var unsyncCmd = &cobra.Command{ Use: "unsync", @@ -29,12 +32,12 @@ to the source before deleting. If changed, it skips deletion to prevent data los } return gv.Unsync(gitvolume.UnsyncOptions{ - DryRun: dryRun, + DryRun: unsyncDryRun, }) }, } func init() { rootCmd.AddCommand(unsyncCmd) - unsyncCmd.Flags().BoolVar(&dryRun, "dry-run", false, "show what would be done without making changes") + unsyncCmd.Flags().BoolVar(&unsyncDryRun, "dry-run", false, "show what would be done without making changes") } diff --git a/docs/translations/README_de.md b/docs/translations/README_de.md index cc0534f..3d70793 100644 --- a/docs/translations/README_de.md +++ b/docs/translations/README_de.md @@ -1,17 +1,17 @@ -> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Français](README_fr.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) +> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Français](README_fr.md) | [Italiano](README_it.md) # git-volume -> **"Behalte den Code in Git, mounte deine Umgebung als Volumes."** +> **„Code in Git, Umgebung als Volumes."** -`git-volume` ist ein CLI-Tool zur zentralen Verwaltung von Umgebungsdateien (`.env`, Secrets usw.) über Git-Worktrees hinweg und deren dynamischem Mounten. +`git-volume` ist ein CLI-Tool, das Umgebungsdateien (`.env`, Secrets usw.) zentral über Git-Worktrees hinweg verwaltet und dynamisch einbindet. -## ✨ Hauptmerkmale +## ✨ Hauptfunktionen -- **Volume-Mounting**: Unterstützt symbolische Links oder Dateikopiermodi -- **Konfigurationsvererbung**: Untergeordnete Worktrees erben automatisch die Einstellungen der Eltern -- **Sicheres Aufräumen**: Geänderte Dateien bleiben beim Unsync erhalten -- **Optimiert für KI-Agenten**: Worktree erstellen + Umgebung konfigurieren mit einem einzigen Befehl +- **Volume-Mounting**: Unterstützung für symbolische Links oder Dateikopien +- **Konfigurationsvererbung**: Kind-Worktrees erben automatisch die Eltern-Konfiguration +- **Sichere Bereinigung**: Vom Benutzer geänderte Dateien werden nicht gelöscht +- **KI-Agenten-optimiert**: Worktree erstellen + Umgebung konfigurieren mit einem einzigen Befehl ## 📦 Installation @@ -33,7 +33,7 @@ go install github.com/laggu/git-volume@latest ## 🚀 Schnellstart -**1. Initialisieren** +**1. Initialisierung** ```bash git volume init ``` @@ -46,7 +46,7 @@ volumes: mode: "copy" ``` -**3. Volumes mounten** +**3. Volumes einbinden** ```bash git volume sync ``` @@ -58,12 +58,17 @@ git volume status ## 📖 Befehle -| Befehl | Beschreibung | -| ------------------- | --------------------------------------------------------------------- | -| `git volume init` | Erstellt das globale Verzeichnis und eine Beispielkonfigurationsdatei | -| `git volume sync` | Mountet Volumes im aktuellen Worktree basierend auf der Konfiguration | -| `git volume unsync` | Entfernt gemountete Volumes (geänderte Dateien bleiben erhalten) | -| `git volume status` | Zeigt den aktuellen Volume-Status an | +| Befehl | Beschreibung | +| -------------------------- | ------------------------------------------------------------------- | +| `git volume init` | Globales Verzeichnis und Beispielkonfiguration erstellen | +| `git volume sync` | Volumes basierend auf Konfiguration im aktuellen Worktree einbinden | +| `git volume unsync` | Eingebundene Volumes entfernen (geänderte Dateien bleiben erhalten) | +| `git volume status` | Aktuellen Volume-Status anzeigen | +| `git volume global add` | Dateien in den globalen Speicher kopieren (`~/.git-volume`) | +| `git volume global list` | Dateien im globalen Speicher auflisten (Baumansicht) | +| `git volume global edit` | Eine Datei im globalen Speicher mit `$EDITOR` bearbeiten | +| `git volume global remove` | Dateien aus dem globalen Speicher entfernen (alias: `rm`) | +| `git volume version` | Versionsinformationen anzeigen | ## ⚙️ Konfigurationsdatei (`git-volume.yaml`) @@ -76,36 +81,80 @@ volumes: - mount: "secrets/prod.key:config/prod.key" mode: "copy" # link (Standard) oder copy + # Aus globalem Speicher einbinden (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Verzeichnis-Mounting (kopiert gesamtes Verzeichnis) + - mount: "configs:app/configs" + mode: "copy" ``` -### Modus-Vergleich +### Modusvergleich -| Modus | Beschreibung | Anwendungsfall | -| ------ | -------------------------- | ----------------------------------------------------- | -| `link` | Erstellt symbolischen Link | Lokale Entwicklung (Änderungen werden sofort wirksam) | -| `copy` | Kopiert Datei | Docker-Builds (Umgebungen ohne Symlink-Unterstützung) | +| Modus | Beschreibung | Anwendungsfall | +| ------ | --------------------------- | ----------------------------------------------- | +| `link` | Symbolischen Link erstellen | Lokale Entwicklung (Änderungen sofort wirksam) | +| `copy` | Datei kopieren | Docker-Builds (Umgebungen ohne Symlink-Support) | ## 🔄 Worktree-Vererbung -Wenn ein untergeordneter Worktree keine `git-volume.yaml` hat, verwendet er automatisch die Konfiguration des übergeordneten (Haupt-)Worktrees. +Wenn ein Kind-Worktree keine `git-volume.yaml` hat, wird automatisch die Konfiguration des Eltern-Worktrees (Haupt-Worktree) verwendet. ```bash # Konfiguration existiert nur im Haupt-Worktree main-repo/ -├── .git/ # gemeinsames Git-Verzeichnis +├── .git/ # git common dir ├── git-volume.yaml # Konfigurationsdatei ├── .env.shared # Quelldatei └── ... -# Das Ausführen von sync in einem untergeordneten Worktree verwendet die Eltern-Konfig +# Sync im Kind-Worktree verwendet die Eltern-Konfiguration cd ../feature-branch -git volume sync # verwendet die git-volume.yaml des Eltern-Worktrees +git volume sync # verwendet git-volume.yaml des Eltern-Worktrees +``` + +## 🌐 Globaler Speicher + +Der globale Speicher (`~/.git-volume`) ermöglicht das Teilen von Dateien über mehrere Projekte hinweg mit dem `@global/`-Präfix. + +```bash +# Dateien zum globalen Speicher hinzufügen +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# Auflisten, bearbeiten und entfernen +git volume global list +git volume global edit config.json +git volume global remove old-secret.key ``` -## 🛡️ Sicherheitsmerkmale +Verwenden Sie `@global/` in Ihrer Konfiguration, um auf diese Dateien zu verweisen: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 CLI-Optionen + +| Flag | Befehle | Beschreibung | +| ----------------- | ---------------- | --------------------------------------------------- | +| `--dry-run` | `sync`, `unsync` | Zeigen was getan würde, ohne Änderungen vorzunehmen | +| `--relative` | `sync` | Relative statt absolute symbolische Links erstellen | +| `--verbose`, `-v` | Alle | Ausführliche Ausgabe | +| `--quiet`, `-q` | Alle | Nicht-Fehler-Ausgaben unterdrücken | +| `--config`, `-c` | Alle | Benutzerdefinierter Konfigurationsdateipfad | + +## 🛡️ Sicherheitsfunktionen -- **Änderungserkennung beim Unsync**: Im Copy-Modus kopierte Dateien bleiben erhalten, wenn sie geändert wurden -- **Idempotent**: Das mehrmalige Ausführen von `sync` ist sicher +- **Ablehnung symbolischer Quellen**: `sync` und `global add` lehnen Quellen ab, die symbolische Links sind +- **Pfad-Traversal-Schutz**: Alle Pfade werden validiert, um Verzeichnis-Escape-Angriffe zu verhindern +- **Änderungserkennung bei Unsync**: Kopierte Dateien und Verzeichnisse werden beibehalten, wenn sie geändert wurden +- **Änderungserkennung bei Status**: Kopierte Dateien, die vom Original abweichen, werden als `MODIFIED` angezeigt +- **Idempotentes Sync**: Mehrfaches Ausführen von `sync` erzeugt immer das gleiche Ergebnis ## 📄 Lizenz diff --git a/docs/translations/README_es.md b/docs/translations/README_es.md index c321939..85bc620 100644 --- a/docs/translations/README_es.md +++ b/docs/translations/README_es.md @@ -2,16 +2,16 @@ # git-volume -> **"Mantén el código en Git, monta tu entorno como volúmenes."** +> **"El código en Git, el entorno como volúmenes."** -`git-volume` es una herramienta de CLI que gestiona de forma centralizada los archivos de entorno (`.env`, secretos, etc.) entre los *worktrees* de Git y los monta dinámicamente. +`git-volume` es una herramienta CLI que gestiona centralmente archivos de entorno (`.env`, secretos, etc.) entre árboles de trabajo Git y los monta dinámicamente. ## ✨ Características principales -- **Montaje de volúmenes**: Soporta modos de enlace simbólico o copia de archivos. -- **Herencia de configuración**: Los *worktrees* secundarios heredan automáticamente la configuración del padre. -- **Limpieza segura**: Los archivos modificados se preservan durante el *unsync*. -- **Optimizado para agentes de IA**: Crea un *worktree* y configura el entorno con un solo comando. +- **Montaje de volúmenes**: Soporte para enlaces simbólicos o copia de archivos +- **Herencia de configuración**: Los árboles de trabajo hijos heredan automáticamente la configuración del padre +- **Limpieza segura**: Los archivos modificados por el usuario no se eliminan +- **Optimizado para agentes IA**: Crear árbol de trabajo + configurar entorno con un solo comando ## 📦 Instalación @@ -51,61 +51,110 @@ volumes: git volume sync ``` -**4. Ver estado** +**4. Verificar estado** ```bash git volume status ``` ## 📖 Comandos -| Comando | Descripción | -| ------------------- | ----------------------------------------------------------------------- | -| `git volume init` | Crea el directorio global y un archivo de configuración de ejemplo. | -| `git volume sync` | Monta volúmenes en el worktree actual según la configuración. | -| `git volume unsync` | Elimina los volúmenes montados (los archivos modificados se conservan). | -| `git volume status` | Muestra el estado actual de los volúmenes. | +| Comando | Descripción | +| -------------------------- | --------------------------------------------------------------- | +| `git volume init` | Crear directorio global y archivo de configuración ejemplo | +| `git volume sync` | Montar volúmenes en el árbol de trabajo actual | +| `git volume unsync` | Eliminar volúmenes montados (se preservan archivos modificados) | +| `git volume status` | Mostrar el estado actual de los volúmenes | +| `git volume global add` | Copiar archivos al almacenamiento global (`~/.git-volume`) | +| `git volume global list` | Listar archivos en el almacenamiento global (vista árbol) | +| `git volume global edit` | Editar un archivo del almacenamiento global con `$EDITOR` | +| `git volume global remove` | Eliminar archivos del almacenamiento global (alias: `rm`) | +| `git volume version` | Mostrar información de versión | ## ⚙️ Archivo de configuración (`git-volume.yaml`) ```yaml volumes: - # Formato simple (predeterminado: enlace simbólico) + # Formato simple (por defecto: enlace simbólico) - ".env.shared:.env" # Con opciones - mount: "secrets/prod.key:config/prod.key" - mode: "copy" # link (predeterminado) o copy + mode: "copy" # link (por defecto) o copy + # Montar desde almacenamiento global (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Montaje de directorios (copia el directorio completo) + - mount: "configs:app/configs" + mode: "copy" ``` ### Comparación de modos -| Modo | Descripción | Caso de uso | -| ------ | ------------------------ | ---------------------------------------------------------------- | -| `link` | Crea un enlace simbólico | Desarrollo local (los cambios se reflejan al instante). | -| `copy` | Copia el archivo | Builds de Docker (entornos sin soporte para enlaces simbólicos). | +| Modo | Descripción | Caso de uso | +| ------ | ---------------------- | ------------------------------------------------------------------- | +| `link` | Crear enlace simbólico | Desarrollo local (los cambios se reflejan al instante) | +| `copy` | Copiar archivo | Compilaciones Docker (entornos sin soporte para enlaces simbólicos) | -## 🔄 Herencia de Worktree +## 🔄 Herencia de árboles de trabajo -Si un *worktree* secundario no tiene `git-volume.yaml`, utiliza automáticamente la configuración del *worktree* principal (padre). +Si un árbol de trabajo hijo no tiene `git-volume.yaml`, se usa automáticamente la configuración del árbol de trabajo padre (principal). ```bash -# La configuración solo existe en el worktree principal +# La configuración solo existe en el árbol de trabajo principal main-repo/ ├── .git/ # git common dir ├── git-volume.yaml # archivo de configuración -├── .env.shared # archivo de origen +├── .env.shared # archivo fuente └── ... -# Ejecutar sync en un worktree secundario usa la configuración del padre +# Al ejecutar sync en el árbol de trabajo hijo se usa la config del padre cd ../feature-branch git volume sync # usa el git-volume.yaml del padre ``` +## 🌐 Almacenamiento global + +El almacenamiento global (`~/.git-volume`) permite compartir archivos entre múltiples proyectos usando el prefijo `@global/`. + +```bash +# Agregar archivos al almacenamiento global +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# Listar, editar y eliminar +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +Use `@global/` en su configuración para referenciar estos archivos: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 Opciones CLI + +| Bandera | Comandos | Descripción | +| ----------------- | ---------------- | ------------------------------------------------------ | +| `--dry-run` | `sync`, `unsync` | Mostrar qué se haría sin realizar cambios | +| `--relative` | `sync` | Crear enlaces simbólicos relativos en vez de absolutos | +| `--verbose`, `-v` | Todos | Salida detallada | +| `--quiet`, `-q` | Todos | Ocultar salida no relacionada con errores | +| `--config`, `-c` | Todos | Ruta personalizada del archivo de configuración | + ## 🛡️ Características de seguridad -- **Detección de cambios al desincronizar**: Los archivos copiados en modo *copy* se conservan si han sido modificados. -- **Idempotente**: Ejecutar `sync` varias veces es seguro. +- **Rechazo de fuentes simbólicas**: `sync` y `global add` rechazan fuentes que son enlaces simbólicos por seguridad +- **Prevención de recorrido de rutas**: Todas las rutas se validan para prevenir ataques de escape de directorio +- **Detección de cambios en Unsync**: Los archivos y directorios copiados se preservan si fueron modificados +- **Detección de cambios en Status**: Los archivos copiados que difieren del origen se muestran como `MODIFIED` +- **Sync idempotente**: Ejecutar `sync` múltiples veces siempre produce el mismo resultado ## 📄 Licencia diff --git a/docs/translations/README_fr.md b/docs/translations/README_fr.md index 2253037..35918f1 100644 --- a/docs/translations/README_fr.md +++ b/docs/translations/README_fr.md @@ -1,17 +1,17 @@ -> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Français](README_fr.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) +> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) # git-volume -> **"Gardez le code dans Git, montez votre environnement comme des volumes."** +> **« Le code dans Git, l'environnement en volumes. »** -`git-volume` est un outil CLI qui gère de manière centralisée les fichiers d'environnement (`.env`, secrets, etc.) à travers les worktrees Git et les monte dynamiquement. +`git-volume` est un outil CLI qui gère centralement les fichiers d'environnement (`.env`, secrets, etc.) entre les arbres de travail Git et les monte dynamiquement. -## ✨ Caractéristiques principales +## ✨ Fonctionnalités principales -- **Montage de volumes** : Prend en charge les modes liens symboliques ou copie de fichiers -- **Héritage de configuration** : Les worktrees enfants héritent automatiquement des paramètres parents -- **Nettoyage sécurisé** : Les fichiers modifiés sont préservés lors de la désynchronisation (unsync) -- **Optimisé pour les agents IA** : Créez un worktree + configurez l'environnement avec une seule commande +- **Montage de volumes** : Support des liens symboliques ou de la copie de fichiers +- **Héritage de configuration** : Les arbres de travail enfants héritent automatiquement de la configuration parent +- **Nettoyage sécurisé** : Les fichiers modifiés par l'utilisateur ne sont pas supprimés +- **Optimisé pour les agents IA** : Créer un arbre de travail + configurer l'environnement en une seule commande ## 📦 Installation @@ -51,19 +51,24 @@ volumes: git volume sync ``` -**4. Vérifier l'état** +**4. Vérifier le statut** ```bash git volume status ``` ## 📖 Commandes -| Commande | Description | -| ------------------- | ------------------------------------------------------------------ | -| `git volume init` | Crée le répertoire global et un fichier de configuration d'exemple | -| `git volume sync` | Monte les volumes dans le worktree actuel selon la configuration | -| `git volume unsync` | Supprime les volumes montés (les fichiers modifiés sont préservés) | -| `git volume status` | Affiche l'état actuel des volumes | +| Commande | Description | +| -------------------------- | ------------------------------------------------------------------- | +| `git volume init` | Créer le répertoire global et le fichier de configuration exemple | +| `git volume sync` | Monter les volumes dans l'arbre de travail actuel | +| `git volume unsync` | Supprimer les volumes montés (les fichiers modifiés sont préservés) | +| `git volume status` | Afficher le statut actuel des volumes | +| `git volume global add` | Copier des fichiers dans le stockage global (`~/.git-volume`) | +| `git volume global list` | Lister les fichiers du stockage global (vue arborescente) | +| `git volume global edit` | Éditer un fichier du stockage global avec `$EDITOR` | +| `git volume global remove` | Supprimer des fichiers du stockage global (alias: `rm`) | +| `git volume version` | Afficher les informations de version | ## ⚙️ Fichier de configuration (`git-volume.yaml`) @@ -74,38 +79,82 @@ volumes: # Avec options - mount: "secrets/prod.key:config/prod.key" - mode: "copy" # link (défaut) ou copy + mode: "copy" # link (par défaut) ou copy + # Monter depuis le stockage global (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Montage de répertoires (copie le répertoire entier) + - mount: "configs:app/configs" + mode: "copy" ``` ### Comparaison des modes -| Mode | Description | Cas d'utilisation | -| ------ | ----------------------- | ---------------------------------------------------- | -| `link` | Crée un lien symbolique | Développement local (les changements sont immédiats) | -| `copy` | Copie le fichier | Builds Docker (environnements sans support symlink) | +| Mode | Description | Cas d'utilisation | +| ------ | ------------------------ | ------------------------------------------------------- | +| `link` | Créer un lien symbolique | Développement local (les modifications sont immédiates) | +| `copy` | Copier le fichier | Builds Docker (environnements sans support symlink) | -## 🔄 Héritage de Worktree +## 🔄 Héritage des arbres de travail -Si un worktree enfant n'a pas de `git-volume.yaml`, il utilise automatiquement la configuration du worktree parent (principal). +Si un arbre de travail enfant n'a pas de `git-volume.yaml`, la configuration de l'arbre de travail parent (principal) est automatiquement utilisée. ```bash -# La configuration n'existe que dans le worktree principal +# La configuration n'existe que dans l'arbre de travail principal main-repo/ -├── .git/ # répertoire commun git +├── .git/ # git common dir ├── git-volume.yaml # fichier de configuration ├── .env.shared # fichier source └── ... -# L'exécution de sync dans un worktree enfant utilise la config parente +# Exécuter sync dans l'arbre de travail enfant utilise la config du parent cd ../feature-branch git volume sync # utilise le git-volume.yaml du parent ``` +## 🌐 Stockage global + +Le stockage global (`~/.git-volume`) permet de partager des fichiers entre plusieurs projets en utilisant le préfixe `@global/`. + +```bash +# Ajouter des fichiers au stockage global +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# Lister, éditer et supprimer +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +Utilisez `@global/` dans votre configuration pour référencer ces fichiers : + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 Options CLI + +| Drapeau | Commandes | Description | +| ----------------- | ---------------- | --------------------------------------------------------- | +| `--dry-run` | `sync`, `unsync` | Afficher ce qui serait fait sans effectuer de changements | +| `--relative` | `sync` | Créer des liens symboliques relatifs au lieu d'absolus | +| `--verbose`, `-v` | Toutes | Sortie détaillée | +| `--quiet`, `-q` | Toutes | Masquer les sorties non liées aux erreurs | +| `--config`, `-c` | Toutes | Chemin personnalisé du fichier de configuration | + ## 🛡️ Fonctionnalités de sécurité -- **Détection de changement lors de l'unsync** : Les fichiers copiés en mode `copy` sont préservés s'ils ont été modifiés -- **Idempotent** : L'exécution de `sync` plusieurs fois est sûre +- **Rejet des sources symboliques** : `sync` et `global add` rejettent les sources qui sont des liens symboliques pour la sécurité +- **Prévention de traversée de chemin** : Tous les chemins sont validés pour prévenir les attaques d'échappement de répertoire +- **Détection de modifications à l'Unsync** : Les fichiers et répertoires copiés sont préservés s'ils ont été modifiés +- **Détection de modifications au Status** : Les fichiers copiés différant de l'original sont affichés comme `MODIFIED` +- **Sync idempotent** : Exécuter `sync` plusieurs fois produit toujours le même résultat ## 📄 Licence diff --git a/docs/translations/README_it.md b/docs/translations/README_it.md index 4e7f6d5..4144a1a 100644 --- a/docs/translations/README_it.md +++ b/docs/translations/README_it.md @@ -1,17 +1,17 @@ -> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Français](README_fr.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) +> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Português](README_pt.md) | [Français](README_fr.md) | [Deutsch](README_de.md) # git-volume -> **"Mantieni il codice in Git, monta il tuo ambiente come volumi."** +> **"Il codice in Git, l'ambiente come volumi."** -`git-volume` è uno strumento CLI che gestisce centralmente i file di ambiente (`.env`, segreti, ecc.) tra i worktree di Git e li monta dinamicamente. +`git-volume` è uno strumento CLI che gestisce centralmente i file di ambiente (`.env`, segreti, ecc.) tra i worktree Git e li monta dinamicamente. -## ✨ Caratteristiche principali +## ✨ Funzionalità principali -- **Montaggio dei volumi**: Supporta modalità link simbolico o copia file -- **Ereditarietà della configurazione**: I worktree figli ereditano automaticamente le impostazioni del genitore -- **Pulizia sicura**: I file modificati vengono preservati durante l'unsync -- **Ottimizzato per agenti AI**: Crea un worktree + configura l'ambiente con un singolo comando +- **Montaggio volumi**: Supporto per link simbolici o copia di file +- **Ereditarietà della configurazione**: I worktree figli ereditano automaticamente la configurazione del genitore +- **Pulizia sicura**: I file modificati dall'utente non vengono eliminati +- **Ottimizzato per agenti IA**: Creare worktree + configurare l'ambiente con un singolo comando ## 📦 Installazione @@ -31,14 +31,14 @@ scoop install git-volume go install github.com/laggu/git-volume@latest ``` -## 🚀 Guida rapida +## 🚀 Avvio rapido **1. Inizializzazione** ```bash git volume init ``` -**2. Creazione di git-volume.yaml** +**2. Creare git-volume.yaml** ```yaml volumes: - ".env.shared:.env" @@ -46,24 +46,29 @@ volumes: mode: "copy" ``` -**3. Montaggio dei volumi** +**3. Montare i volumi** ```bash git volume sync ``` -**4. Verifica dello stato** +**4. Verificare lo stato** ```bash git volume status ``` ## 📖 Comandi -| Comando | Descrizione | -| ------------------- | ---------------------------------------------------------------- | -| `git volume init` | Crea la directory globale e un file di configurazione di esempio | -| `git volume sync` | Monta i volumi nel worktree attuale in base alla configurazione | -| `git volume unsync` | Rimuove i volumi montati (i file modificati vengono preservati) | -| `git volume status` | Visualizza lo stato attuale dei volumi | +| Comando | Descrizione | +| -------------------------- | -------------------------------------------------------------------- | +| `git volume init` | Creare la directory globale e il file di configurazione esempio | +| `git volume sync` | Montare i volumi nel worktree attuale basandosi sulla configurazione | +| `git volume unsync` | Rimuovere i volumi montati (i file modificati vengono preservati) | +| `git volume status` | Mostrare lo stato attuale dei volumi | +| `git volume global add` | Copiare file nell'archivio globale (`~/.git-volume`) | +| `git volume global list` | Elencare i file nell'archivio globale (vista ad albero) | +| `git volume global edit` | Modificare un file dell'archivio globale con `$EDITOR` | +| `git volume global remove` | Rimuovere file dall'archivio globale (alias: `rm`) | +| `git volume version` | Mostrare le informazioni sulla versione | ## ⚙️ File di configurazione (`git-volume.yaml`) @@ -76,36 +81,80 @@ volumes: - mount: "secrets/prod.key:config/prod.key" mode: "copy" # link (predefinito) o copy + # Montare dall'archivio globale (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Montaggio directory (copia l'intera directory) + - mount: "configs:app/configs" + mode: "copy" ``` -### Confronto modalità +### Confronto modi -| Modalità | Descrizione | Caso d'uso | -| -------- | ---------------------- | ---------------------------------------------- | -| `link` | Crea un link simbolico | Sviluppo locale (le modifiche sono immediate) | -| `copy` | Copia il file | Build Docker (ambienti senza supporto symlink) | +| Modo | Descrizione | Caso d'uso | +| ------ | --------------------- | ----------------------------------------------------------- | +| `link` | Creare link simbolico | Sviluppo locale (le modifiche si riflettono immediatamente) | +| `copy` | Copiare il file | Build Docker (ambienti senza supporto link simbolici) | -## 🔄 Ereditarietà Worktree +## 🔄 Ereditarietà dei worktree -Se un worktree figlio non ha `git-volume.yaml`, utilizza automaticamente la configurazione del worktree genitore (principale). +Se un worktree figlio non ha un `git-volume.yaml`, viene automaticamente utilizzata la configurazione del worktree genitore (principale). ```bash # La configurazione esiste solo nel worktree principale main-repo/ -├── .git/ # directory comune git +├── .git/ # git common dir ├── git-volume.yaml # file di configurazione ├── .env.shared # file sorgente └── ... -# L'esecuzione di sync in un worktree figlio usa la config del genitore +# Eseguire sync nel worktree figlio usa la config del genitore cd ../feature-branch git volume sync # usa il git-volume.yaml del genitore ``` +## 🌐 Archivio globale + +L'archivio globale (`~/.git-volume`) consente di condividere file tra più progetti usando il prefisso `@global/`. + +```bash +# Aggiungere file all'archivio globale +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# Elencare, modificare e rimuovere +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +Usa `@global/` nella configurazione per fare riferimento a questi file: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 Opzioni CLI + +| Flag | Comandi | Descrizione | +| ----------------- | ---------------- | ------------------------------------------------------ | +| `--dry-run` | `sync`, `unsync` | Mostrare cosa verrebbe fatto senza apportare modifiche | +| `--relative` | `sync` | Creare link simbolici relativi invece di assoluti | +| `--verbose`, `-v` | Tutti | Output dettagliato | +| `--quiet`, `-q` | Tutti | Nascondere l'output non correlato agli errori | +| `--config`, `-c` | Tutti | Percorso personalizzato del file di configurazione | + ## 🛡️ Funzionalità di sicurezza -- **Rilevamento modifiche all'unsync**: I file copiati in modalità `copy` vengono preservati se modificati -- **Idempotente**: L'esecuzione di `sync` più volte è sicura +- **Rifiuto sorgenti simboliche**: `sync` e `global add` rifiutano sorgenti che sono link simbolici per sicurezza +- **Prevenzione path traversal**: Tutti i percorsi vengono validati per prevenire attacchi di escape dalla directory +- **Rilevamento modifiche all'Unsync**: I file e le directory copiate vengono preservati se modificati +- **Rilevamento modifiche allo Status**: I file copiati diversi dall'originale vengono mostrati come `MODIFIED` +- **Sync idempotente**: Eseguire `sync` più volte produce sempre lo stesso risultato ## 📄 Licenza diff --git a/docs/translations/README_ja.md b/docs/translations/README_ja.md index 60fa714..b0e0d51 100644 --- a/docs/translations/README_ja.md +++ b/docs/translations/README_ja.md @@ -2,16 +2,16 @@ # git-volume -> **"コードはGitに、環境はボリュームとしてマウント。"** +> **「コードはGitに、環境はボリュームとして。」** -`git-volume`は、複数のGitワークツリー間で環境設定ファイル(`.env`、シークレットなど)を一元管理し、動的にマウントするためのCLIツールです。 +`git-volume`は、Gitワークツリー間で環境ファイル(`.env`、シークレットなど)を一元管理し、動的にマウントするCLIツールです。 ## ✨ 主な機能 -- **ボリュームマウント**: シンボリックリンクまたはファイルコピーモードをサポート -- **設定の継承**: 子ワークツリーは親ツリーの設定を自動的に継承 -- **安全なクリーンアップ**: 変更されたファイルはアンシンク時に保護 -- **AIエージェント最適化**: ワークツリー作成と環境構築を1つのコマンドで実行 +- **ボリュームマウント**: シンボリックリンクまたはファイルコピーに対応 +- **設定の継承**: 子ワークツリーが親の設定を自動継承 +- **安全なクリーンアップ**: ユーザーが変更したファイルは削除しない +- **AIエージェント最適化**: 一つのコマンドでワークツリー作成+環境構成 ## 📦 インストール @@ -38,7 +38,7 @@ go install github.com/laggu/git-volume@latest git volume init ``` -**2. git-volume.yaml の作成** +**2. git-volume.yamlの作成** ```yaml volumes: - ".env.shared:.env" @@ -51,61 +51,110 @@ volumes: git volume sync ``` -**4. ステータスの確認** +**4. ステータス確認** ```bash git volume status ``` ## 📖 コマンド -| コマンド | 説明 | -| ------------------- | ------------------------------------------ | -| `git volume init` | グローバルディレクトリとサンプル設定の作成 | -| `git volume sync` | 設定に基づきボリュームをマウント | -| `git volume unsync` | マウントされたボリュームを削除 | -| `git volume status` | 現在のボリュームステータスを表示 | +| コマンド | 説明 | +| -------------------------- | ------------------------------------------------------- | +| `git volume init` | グローバルディレクトリとサンプル設定ファイルを作成 | +| `git volume sync` | 設定に基づきボリュームを現在のワークツリーにマウント | +| `git volume unsync` | マウントされたボリュームを削除(変更ファイルは保持) | +| `git volume status` | 現在のボリュームステータスを表示 | +| `git volume global add` | グローバルストレージ(`~/.git-volume`)にファイルをコピー | +| `git volume global list` | グローバルストレージのファイル一覧(ツリー表示) | +| `git volume global edit` | グローバルストレージのファイルを`$EDITOR`で編集 | +| `git volume global remove` | グローバルストレージからファイルを削除 (alias: `rm`) | +| `git volume version` | バージョン情報を表示 | ## ⚙️ 設定ファイル (`git-volume.yaml`) ```yaml volumes: - # シンプルな形式(デフォルト:シンボリックリンク) + # シンプル形式(デフォルト: シンボリックリンク) - ".env.shared:.env" # オプション指定 - mount: "secrets/prod.key:config/prod.key" - mode: "copy" # link (デフォルト) または copy + mode: "copy" # link(デフォルト)または copy + # グローバルストレージからマウント (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # ディレクトリマウント(ディレクトリ全体をコピー) + - mount: "configs:app/configs" + mode: "copy" ``` ### モード比較 -| モード | 説明 | ユースケース | -| ------ | ---------------------- | ------------------------------------------------ | -| `link` | シンボリックリンク作成 | ローカル開発(変更が即座に反映) | -| `copy` | ファイルコピー | Dockerビルド(シンボリックリンク未サポート環境) | +| モード | 説明 | 用途 | +| ------ | ---------------------- | -------------------------------------------- | +| `link` | シンボリックリンク作成 | ローカル開発(変更が即座に反映) | +| `copy` | ファイルコピー | Dockerビルド(シンボリックリンク非対応環境) | -## 🔄 ワークツリーの継承 +## 🔄 ワークツリー継承 -子ワークツリーに `git-volume.yaml` がない場合、自動的に親(メイン)ワークツリーの設定を使用します。 +子ワークツリーに`git-volume.yaml`がない場合、親(メイン)ワークツリーの設定を自動的に使用します。 ```bash -# メインワークツリーのみに設定が存在 +# メインワークツリーにのみ設定が存在 main-repo/ ├── .git/ # git common dir ├── git-volume.yaml # 設定ファイル ├── .env.shared # ソースファイル └── ... -# 子ワークツリーでsyncを実行すると親の設定が使用される +# 子ワークツリーでsync実行時に親の設定を使用 cd ../feature-branch -git volume sync # 親の git-volume.yaml を使用 +git volume sync # 親のgit-volume.yamlを使用 +``` + +## 🌐 グローバルストレージ + +グローバルストレージ(`~/.git-volume`)を使用すると、`@global/`プレフィックスで複数のプロジェクト間でファイルを共有できます。 + +```bash +# グローバルストレージにファイルを追加 +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# 一覧表示、編集、削除 +git volume global list +git volume global edit config.json +git volume global remove old-secret.key ``` +設定ファイルで`@global/`を使用して参照します: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 CLIオプション + +| フラグ | 対象コマンド | 説明 | +| ----------------- | ---------------- | ---------------------------------------- | +| `--dry-run` | `sync`, `unsync` | 実際の変更なしに実行内容を表示 | +| `--relative` | `sync` | 絶対パスの代わりに相対パスのリンクを作成 | +| `--verbose`, `-v` | 全て | 詳細出力 | +| `--quiet`, `-q` | 全て | エラー以外の出力を非表示 | +| `--config`, `-c` | 全て | 設定ファイルパスの指定 | + ## 🛡️ 安全機能 -- **アンシンク時の変更検知**: Copyモードでコピーされたファイルが変更されている場合、削除せずに保持 -- **べき等性**: `sync`を複数回実行しても安全 +- **シンボリックリンクソース拒否**: `sync`と`global add`でシンボリックリンクソースをセキュリティ上拒否 +- **パストラバーサル防止**: 全てのパスに対してディレクトリエスケープ攻撃を検証 +- **Unsync時の変更検出**: Copyモードでコピーされたファイル・ディレクトリは変更されていれば保持 +- **Status変更検出**: コピーされたファイルが元ファイルと異なる場合`MODIFIED`と表示 +- **べき等性保証**: `sync`を何度実行しても常に同じ結果 ## 📄 ライセンス diff --git a/docs/translations/README_ko.md b/docs/translations/README_ko.md index 0c9a5ed..37ec73d 100644 --- a/docs/translations/README_ko.md +++ b/docs/translations/README_ko.md @@ -58,12 +58,17 @@ git volume status ## 📖 명령어 -| 명령어 | 설명 | -| ------------------- | ------------------------------------------- | -| `git volume init` | 글로벌 디렉토리 생성 및 샘플 설정 파일 생성 | -| `git volume sync` | 설정에 따라 볼륨을 현재 워크트리에 마운트 | -| `git volume unsync` | 마운트된 볼륨 제거 (수정된 파일은 보존) | -| `git volume status` | 현재 볼륨 상태 표시 | +| 명령어 | 설명 | +| -------------------------- | ------------------------------------------- | +| `git volume init` | 글로벌 디렉토리 생성 및 샘플 설정 파일 생성 | +| `git volume sync` | 설정에 따라 볼륨을 현재 워크트리에 마운트 | +| `git volume unsync` | 마운트된 볼륨 제거 (수정된 파일은 보존) | +| `git volume status` | 현재 볼륨 상태 표시 | +| `git volume global add` | 글로벌 저장소(`~/.git-volume`)에 파일 복사 | +| `git volume global list` | 글로벌 저장소의 파일 목록 (트리 뷰) | +| `git volume global edit` | 글로벌 저장소의 파일을 `$EDITOR`로 편집 | +| `git volume global remove` | 글로벌 저장소에서 파일 삭제 (alias: `rm`) | +| `git volume version` | 버전 정보 출력 | ## ⚙️ 설정 파일 (`git-volume.yaml`) @@ -76,6 +81,12 @@ volumes: - mount: "secrets/prod.key:config/prod.key" mode: "copy" # link (기본) 또는 copy + # 글로벌 저장소에서 마운트 (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # 디렉토리 마운트 (디렉토리 전체 복사) + - mount: "configs:app/configs" + mode: "copy" ``` ### 모드 비교 @@ -102,10 +113,48 @@ cd ../feature-branch git volume sync # 부모의 git-volume.yaml 사용 ``` +## 🌐 글로벌 저장소 + +글로벌 저장소(`~/.git-volume`)를 사용하면 `@global/` 접두사를 통해 여러 프로젝트에서 파일을 공유할 수 있습니다. + +```bash +# 글로벌 저장소에 파일 추가 +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# 목록 확인, 편집, 삭제 +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +설정 파일에서 `@global/`로 참조하여 사용합니다: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 CLI 옵션 + +| 플래그 | 대상 명령어 | 설명 | +| ----------------- | ---------------- | ----------------------------------------- | +| `--dry-run` | `sync`, `unsync` | 실제 변경 없이 수행할 작업만 표시 | +| `--relative` | `sync` | 절대 경로 대신 상대 경로 심볼릭 링크 생성 | +| `--verbose`, `-v` | 전체 | 상세 출력 | +| `--quiet`, `-q` | 전체 | 에러 외 출력 숨김 | +| `--config`, `-c` | 전체 | 설정 파일 경로 지정 | + ## 🛡️ 안전 장치 -- **Unsync 시 변경 감지**: Copy 모드로 복사된 파일이 수정되었으면 삭제하지 않고 보존 -- **멱등성**: `sync`를 여러 번 실행해도 안전 +- **심볼릭 링크 소스 차단**: `sync`와 `global add`에서 심볼릭 링크 소스를 보안상 거부 +- **경로 탐색 방지**: 모든 경로에 대해 디렉토리 이스케이프 공격 검증 +- **Unsync 시 변경 감지**: Copy 모드로 복사된 파일 및 디렉토리가 수정되었으면 보존 +- **Status 변경 감지**: 복사된 파일이 원본과 다르면 `MODIFIED`로 표시 +- **멱등성 보장**: `sync`를 여러 번 실행해도 항상 동일한 결과 ## 📄 라이선스 diff --git a/docs/translations/README_pt.md b/docs/translations/README_pt.md index 1a4d14b..fe0eca2 100644 --- a/docs/translations/README_pt.md +++ b/docs/translations/README_pt.md @@ -1,17 +1,17 @@ -> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Français](README_fr.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) | [Português](README_pt.md) +> 🌐 [English](../../README.md) | [한국어](README_ko.md) | [日本語](README_ja.md) | [中文](README_zh.md) | [Español](README_es.md) | [Français](README_fr.md) | [Deutsch](README_de.md) | [Italiano](README_it.md) # git-volume -> **"Mantenha o código no Git, monte o seu ambiente como volumes."** +> **"Código no Git, ambiente como volumes."** -`git-volume` é uma ferramenta CLI que gere centralizadamente ficheiros de ambiente (`.env`, segredos, etc.) entre os *worktrees* do Git e os monta dinamicamente. +`git-volume` é uma ferramenta CLI que gerencia centralmente arquivos de ambiente (`.env`, segredos, etc.) entre árvores de trabalho Git e os monta dinamicamente. -## ✨ Principais Características +## ✨ Principais recursos -- **Montagem de Volumes**: Suporta modos de ligação simbólica ou cópia de ficheiros. -- **Herança de Configuração**: Os *worktrees* filhos herdam automaticamente as definições do pai. -- **Limpeza Segura**: Os ficheiros modificados são preservados durante o *unsync*. -- **Otimizado para Agentes de IA**: Crie um *worktree* e configure o ambiente com um único comando. +- **Montagem de volumes**: Suporte para links simbólicos ou cópia de arquivos +- **Herança de configuração**: Árvores de trabalho filhas herdam automaticamente a configuração pai +- **Limpeza segura**: Arquivos modificados pelo usuário não são excluídos +- **Otimizado para agentes IA**: Criar árvore de trabalho + configurar ambiente com um único comando ## 📦 Instalação @@ -31,7 +31,7 @@ scoop install git-volume go install github.com/laggu/git-volume@latest ``` -## 🚀 Início Rápido +## 🚀 Início rápido **1. Inicializar** ```bash @@ -46,66 +46,115 @@ volumes: mode: "copy" ``` -**3. Montar Volumes** +**3. Montar volumes** ```bash git volume sync ``` -**4. Verificar Estado** +**4. Verificar status** ```bash git volume status ``` ## 📖 Comandos -| Comando | Descrição | -| ------------------- | ----------------------------------------------------------------- | -| `git volume init` | Cria o diretório global e um ficheiro de configuração de exemplo. | -| `git volume sync` | Monta volumes no worktree atual com base na configuração. | -| `git volume unsync` | Remove volumes montados (ficheiros modificados são preservados). | -| `git volume status` | Exibe o estado atual dos volumes. | +| Comando | Descrição | +| -------------------------- | ---------------------------------------------------------------- | +| `git volume init` | Criar diretório global e arquivo de configuração exemplo | +| `git volume sync` | Montar volumes na árvore de trabalho atual | +| `git volume unsync` | Remover volumes montados (arquivos modificados são preservados) | +| `git volume status` | Exibir o status atual dos volumes | +| `git volume global add` | Copiar arquivos para o armazenamento global (`~/.git-volume`) | +| `git volume global list` | Listar arquivos no armazenamento global (visualização em árvore) | +| `git volume global edit` | Editar um arquivo do armazenamento global com `$EDITOR` | +| `git volume global remove` | Remover arquivos do armazenamento global (alias: `rm`) | +| `git volume version` | Exibir informações de versão | -## ⚙️ Ficheiro de Configuração (`git-volume.yaml`) +## ⚙️ Arquivo de configuração (`git-volume.yaml`) ```yaml volumes: - # Formato simples (predefinido: ligação simbólica) + # Formato simples (padrão: link simbólico) - ".env.shared:.env" # Com opções - mount: "secrets/prod.key:config/prod.key" - mode: "copy" # link (predefinido) ou copy + mode: "copy" # link (padrão) ou copy + # Montar do armazenamento global (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # Montagem de diretórios (copia o diretório inteiro) + - mount: "configs:app/configs" + mode: "copy" ``` -### Comparação de Modos +### Comparação de modos -| Modo | Descrição | Caso de Uso | -| ------ | ---------------------- | ------------------------------------------------------------------ | -| `link` | Cria ligação simbólica | Desenvolvimento local (as alterações refletem-se imediatamente). | -| `copy` | Copia ficheiro | Builds de Docker (ambientes sem suporte para ligações simbólicas). | +| Modo | Descrição | Caso de uso | +| ------ | -------------------- | --------------------------------------------------------- | +| `link` | Criar link simbólico | Desenvolvimento local (alterações refletem imediatamente) | +| `copy` | Copiar arquivo | Builds Docker (ambientes sem suporte a links simbólicos) | -## 🔄 Herança de Worktree +## 🔄 Herança de árvores de trabalho -Se um *worktree* filho não tiver `git-volume.yaml`, ele utiliza automaticamente a configuração do *worktree* pai (principal). +Se uma árvore de trabalho filha não tiver `git-volume.yaml`, a configuração da árvore de trabalho pai (principal) é usada automaticamente. ```bash -# A configuração existe apenas no worktree principal +# Configuração existe apenas na árvore de trabalho principal main-repo/ -├── .git/ # diretório comum do git -├── git-volume.yaml # ficheiro de configuração -├── .env.shared # ficheiro de origem +├── .git/ # git common dir +├── git-volume.yaml # arquivo de configuração +├── .env.shared # arquivo fonte └── ... -# Executar sync num worktree filho usa a configuração do pai +# Ao executar sync na árvore de trabalho filha, usa a config do pai cd ../feature-branch git volume sync # usa o git-volume.yaml do pai ``` -## 🛡️ Funcionalidades de Segurança +## 🌐 Armazenamento global + +O armazenamento global (`~/.git-volume`) permite compartilhar arquivos entre múltiplos projetos usando o prefixo `@global/`. + +```bash +# Adicionar arquivos ao armazenamento global +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# Listar, editar e remover +git volume global list +git volume global edit config.json +git volume global remove old-secret.key +``` + +Use `@global/` em sua configuração para referenciar esses arquivos: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 Opções CLI + +| Flag | Comandos | Descrição | +| ----------------- | ---------------- | ---------------------------------------------------- | +| `--dry-run` | `sync`, `unsync` | Mostrar o que seria feito sem realizar alterações | +| `--relative` | `sync` | Criar links simbólicos relativos em vez de absolutos | +| `--verbose`, `-v` | Todos | Saída detalhada | +| `--quiet`, `-q` | Todos | Ocultar saída não relacionada a erros | +| `--config`, `-c` | Todos | Caminho personalizado do arquivo de configuração | + +## 🛡️ Recursos de segurança -- **Deteção de Alterações no Unsync**: Ficheiros copiados em modo *copy* são preservados se modificados. -- **Idempotente**: Executar `sync` várias vezes é seguro. +- **Rejeição de fontes simbólicas**: `sync` e `global add` rejeitam fontes que são links simbólicos por segurança +- **Prevenção de travessia de caminho**: Todos os caminhos são validados para prevenir ataques de escape de diretório +- **Detecção de alterações no Unsync**: Arquivos e diretórios copiados são preservados se modificados +- **Detecção de alterações no Status**: Arquivos copiados diferentes do original são exibidos como `MODIFIED` +- **Sync idempotente**: Executar `sync` múltiplas vezes sempre produz o mesmo resultado ## 📄 Licença diff --git a/docs/translations/README_zh.md b/docs/translations/README_zh.md index c0d6676..eb87b54 100644 --- a/docs/translations/README_zh.md +++ b/docs/translations/README_zh.md @@ -2,16 +2,16 @@ # git-volume -> **"代码归 Git,环境归卷。"** +> **"代码留在 Git,环境作为卷挂载。"** -`git-volume` 是一个 CLI 工具,用于在 Git 工作区(worktrees)之间集中管理环境配置文件(如 `.env`、机密信息等)并动态挂载它们。 +`git-volume` 是一个 CLI 工具,用于在 Git 工作树之间集中管理环境文件(`.env`、密钥等)并动态挂载。 ## ✨ 主要功能 -- **卷挂载**:支持符号链接或文件复制模式 -- **配置继承**:子工作区自动继承父工作区的设置 -- **安全清理**:在取消同步(unsync)时保护已修改的文件 -- **AI 代理优化**:通过一条命令即可创建工作区并配置环境 +- **卷挂载**: 支持符号链接或文件复制模式 +- **配置继承**: 子工作树自动继承父工作树的配置 +- **安全清理**: 用户修改过的文件不会被删除 +- **AI 代理优化**: 一条命令即可创建工作树并配置环境 ## 📦 安装 @@ -31,7 +31,7 @@ scoop install git-volume go install github.com/laggu/git-volume@latest ``` -## 🚀 快速入门 +## 🚀 快速开始 **1. 初始化** ```bash @@ -51,19 +51,24 @@ volumes: git volume sync ``` -**4. 查看状态** +**4. 检查状态** ```bash git volume status ``` -## 📖 常用命令 +## 📖 命令 -| 命令 | 描述 | -| ------------------- | ---------------------------------- | -| `git volume init` | 创建全局目录和示例配置文件 | -| `git volume sync` | 根据配置将卷挂载到当前工作区 | -| `git volume unsync` | 移除已挂载的卷(保留已修改的文件) | -| `git volume status` | 显示当前卷状态 | +| 命令 | 说明 | +| -------------------------- | ------------------------------------- | +| `git volume init` | 创建全局目录和示例配置文件 | +| `git volume sync` | 根据配置将卷挂载到当前工作树 | +| `git volume unsync` | 移除已挂载的卷(已修改的文件会保留) | +| `git volume status` | 显示当前卷的状态 | +| `git volume global add` | 将文件复制到全局存储(`~/.git-volume`) | +| `git volume global list` | 列出全局存储中的文件(树形视图) | +| `git volume global edit` | 使用 `$EDITOR` 编辑全局存储中的文件 | +| `git volume global remove` | 从全局存储中删除文件 (alias: `rm`) | +| `git volume version` | 打印版本信息 | ## ⚙️ 配置文件 (`git-volume.yaml`) @@ -72,40 +77,84 @@ volumes: # 简单格式(默认:符号链接) - ".env.shared:.env" - # 带有选项的格式 + # 指定选项 - mount: "secrets/prod.key:config/prod.key" - mode: "copy" # link (默认) 或 copy + mode: "copy" # link(默认)或 copy + # 从全局存储挂载 (~/.git-volume) + - "@global/secrets/prod.key:config/key" + + # 目录挂载(复制整个目录) + - mount: "configs:app/configs" + mode: "copy" ``` -### 模式对比 +### 模式比较 -| 模式 | 描述 | 使用场景 | +| 模式 | 说明 | 用途 | | ------ | ------------ | ----------------------------------- | -| `link` | 创建符号链接 | 本地开发(更改立即生效) | +| `link` | 创建符号链接 | 本地开发(修改立即反映) | | `copy` | 复制文件 | Docker 构建(不支持符号链接的环境) | -## 🔄 工作区继承 +## 🔄 工作树继承 -如果子工作区没有 `git-volume.yaml`,它会自动使用父(主)工作区的配置。 +如果子工作树中没有 `git-volume.yaml`,将自动使用父(主)工作树的配置。 ```bash -# 仅在主工作区存在配置 +# 仅在主工作树中存在配置 main-repo/ ├── .git/ # git common dir ├── git-volume.yaml # 配置文件 ├── .env.shared # 源文件 └── ... -# 在子工作区运行 sync 将使用父配置 +# 在子工作树中运行 sync 时使用父级配置 cd ../feature-branch -git volume sync # 使用父工作区的 git-volume.yaml +git volume sync # 使用父级的 git-volume.yaml +``` + +## 🌐 全局存储 + +全局存储(`~/.git-volume`)允许通过 `@global/` 前缀在多个项目之间共享文件。 + +```bash +# 向全局存储添加文件 +git volume global add .env +git volume global add .env.local --as .env +git volume global add .env config.json --path myproject + +# 列出、编辑和删除 +git volume global list +git volume global edit config.json +git volume global remove old-secret.key ``` -## 🛡️ 安全特性 +在配置文件中使用 `@global/` 引用这些文件: + +```yaml +volumes: + - "@global/.env:.env" + - mount: "@global/secrets/prod.key:config/key" + mode: "copy" +``` + +## 🔧 CLI 选项 + +| 标志 | 适用命令 | 说明 | +| ----------------- | ---------------- | -------------------------------- | +| `--dry-run` | `sync`, `unsync` | 不做实际更改,仅显示将执行的操作 | +| `--relative` | `sync` | 创建相对路径符号链接而非绝对路径 | +| `--verbose`, `-v` | 全部 | 详细输出 | +| `--quiet`, `-q` | 全部 | 隐藏非错误输出 | +| `--config`, `-c` | 全部 | 指定配置文件路径 | + +## 🛡️ 安全功能 -- **取消同步时的更改检测**:以 copy 模式复制的文件如果已被修改,则会被保留 -- **幂等性**:多次运行 `sync` 是安全的 +- **符号链接源拒绝**: `sync` 和 `global add` 出于安全考虑拒绝符号链接源 +- **路径遍历防护**: 所有路径都经过验证以防止目录逃逸攻击 +- **Unsync 变更检测**: Copy 模式复制的文件和目录如果已修改则保留 +- **Status 变更检测**: 复制的文件与源文件不同时显示 `MODIFIED` +- **幂等性保证**: 多次运行 `sync` 始终产生相同结果 ## 📄 许可证 diff --git a/gv b/gv deleted file mode 100755 index 20703f2..0000000 Binary files a/gv and /dev/null differ diff --git a/test/integration.sh b/test/integration.sh index 220e3b3..d5bf224 100755 --- a/test/integration.sh +++ b/test/integration.sh @@ -384,6 +384,68 @@ fi # Clean up for next tests rm -rf copied_dir +# ----------------------------------------------------------------------------- +# Test: Error Visibility (Bad Flag) +# ----------------------------------------------------------------------------- +log "TEST" "Testing Error Visibility (Bad Flag)..." + +# Capture stdout and stderr +if OUTPUT=$("$GV_BIN" sync --unknown-flag 2>&1); then + fail "Command should have failed but succeeded" +else + # Command failed as expected, check output for error message + if grep -q "unknown flag: --unknown-flag" <<< "$OUTPUT"; then + pass "Error message visible on stderr/stdout" + else + fail "Error message NOT found in output" + echo "Output: $OUTPUT" + fi +fi + +# ----------------------------------------------------------------------------- +# Test: Sync Dry Run Isolation +# ----------------------------------------------------------------------------- +log "TEST" "Testing Sync Dry Run..." + +# Set up a volume to sync +echo "DATA" > source.txt +cat > git-volume.yaml </dev/null 2>&1 +git commit -m "init" >/dev/null 2>&1 + +# Run sync with dry-run +"$GV_BIN" sync --dry-run >/dev/null + +if [[ ! -f "target.txt" ]]; then + pass "sync --dry-run did not create file" +else + fail "sync --dry-run CREATED file (meant to be dry run)" +fi + +# ----------------------------------------------------------------------------- +# Test: Unsync Dry Run Isolation +# ----------------------------------------------------------------------------- +log "TEST" "Testing Unsync Dry Run..." + +# Actually sync first +"$GV_BIN" sync >/dev/null +if [[ ! -f "target.txt" ]]; then + fail "Setup failed: sync did not create file" +fi + +# Run unsync with dry-run +"$GV_BIN" unsync --dry-run >/dev/null + +if [[ -f "target.txt" ]]; then + pass "unsync --dry-run did not remove file" +else + fail "unsync --dry-run REMOVED file (meant to be dry run)" +fi + # ----------------------------------------------------------------------------- # Summary # -----------------------------------------------------------------------------