From 85df8ffe8d6f623e9e195220e5a70edffdad7507 Mon Sep 17 00:00:00 2001 From: Elvis Claros Castro Date: Sat, 26 Sep 2026 18:44:59 -0300 Subject: Initial import: two-way sync CLI for self-hosted Overleaf CE --- README.es.md | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 README.es.md (limited to 'README.es.md') diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..1630d24 --- /dev/null +++ b/README.es.md @@ -0,0 +1,102 @@ +# overleaf-ce-sync + +[English](README.md) + +Sincronización bidireccional «al estilo git» para **Overleaf Community Edition +autoalojado**. + +La integración nativa con Git (`git-bridge`) es una función de Server Pro y no +se puede usar con CE: la Snapshot API y el servidor OAuth2 que necesita están en +módulos de código cerrado. Esta herramienta ofrece lo más parecido: bajar un +proyecto al disco, versionarlo con tu propio `git` y subir los cambios. + +Usa los mismos endpoints HTTP que la interfaz web. El login por HTTP simple, que +en overleaf.com no funciona por el CAPTCHA, anda bien en CE porque CE no tiene +CAPTCHA. + +## Instalación + +Con [pipx](https://pipx.pypa.io) (entorno aislado, `overleaf-ce-sync` en el PATH): + +```bash +git clone https://git.all.ar/pub/overleaf-ce-sync.git +cd overleaf-ce-sync +pipx install -e . # -e = editable: los cambios al código se aplican sin reinstalar +``` + +La única dependencia es `requests`; hace falta Python 3.8 o posterior. + +Si pipx avisa que `~/.local/bin` no está en el PATH, ejecutá `pipx ensurepath` y +abrí otra terminal. + +## Uso + +```bash +# 1. iniciar sesión una vez por servidor (la cookie se guarda en ~/.config/overleaf-ce, con permisos 0600) +overleaf-ce-sync login --host overleaf.example.com --email vos@example.com + +# 2. buscar el id del proyecto +overleaf-ce-sync list + +# 3. clonarlo en un repo git +overleaf-ce-sync clone milibro +cd milibro + +# 4. ciclo normal +overleaf-ce-sync pull # trae los cambios remotos (pisa los locales) +# ...editar, git commit... +overleaf-ce-sync push # sube los archivos cambiados localmente +``` + +Después del primer `pull`/`clone`, el servidor y el id del proyecto quedan +guardados en `.overleaf-ce.json`, así que dentro del directorio alcanza con +`overleaf-ce-sync pull` / `overleaf-ce-sync push`. + +## Cómo funciona + +La sincronización se ancla en **commits de git**: `push` publica solo lo que +commiteaste, nunca las ediciones sueltas del árbol de trabajo. + +- **pull** → `GET /Project//download/zip`, lo extrae sobre el árbol de + trabajo, hace un «commit de sincronización» y lo recuerda como + `last_sync_commit` en `.overleaf-ce.json`. +- **push** → sube el estado **commiteado** (HEAD). Compara + `last_sync_commit..HEAD`, sube el contenido *commiteado* de cada archivo + cambiado (`git show HEAD:`) con `POST /Project//upload` (pisa por + nombre) y avanza `last_sync_commit` a HEAD. Lo no commiteado se ignora. +- El endpoint de subida necesita el **id de la carpeta raíz** del proyecto. Se + obtiene una sola vez por socket.io con **xhr-polling** (HTTP simple: funciona + detrás de cualquier proxy inverso, sin upgrade a websocket) a partir del + evento `joinProjectResponse`, y se guarda en `.overleaf-ce.json`. + +## Limitaciones + +- **push solo manda cambios commiteados.** Editá, hacé `git commit` y después + `push`. Un archivo con cambios sin commitear se saltea (y te avisa). +- **Los borrados no se propagan.** Los archivos que borrás en tus commits se + informan pero NO se borran en Overleaf (por seguridad). Borralos desde la web; + usá `pull --prune` para reflejar en tu copia los borrados remotos. +- **pull pisa el árbol de trabajo** y se niega si hay cambios sin commitear + (`--force` para forzarlo). Commitea solo lo que trae, así que tu historial + intercala commits «overleaf pull» con los tuyos. +- **Binario o documento**: lo decide Overleaf por archivo; volver a subir crea + versiones nuevas en su historial, por eso push solo manda los archivos cuyo + contenido commiteado cambió. +- No cierres sesión en el navegador con la que iniciaste: Overleaf puede + revocar la cookie. + +## Alternativa: id de la carpeta raíz sin socket.io + +Si la detección por xhr-polling falla con tu instalación, sacá el id una vez de +Mongo en el servidor y pasalo con `--root-folder-id` (después queda guardado): + +```bash +docker compose exec mongo mongosh sharelatex --quiet --eval \ + 'printjson(db.projects.findOne({_id:ObjectId("")},{ "rootFolder._id":1}))' + +overleaf-ce-sync push --root-folder-id +``` + +## Licencia + +MIT -- cgit v1.2.3